2011-12-03 06:16:29 +08:00
|
|
|
//===-- Analysis.cpp - CodeGen LLVM IR Analysis Utilities -----------------===//
|
2010-04-21 09:22:34 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// 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
|
2010-04-21 09:22:34 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2014-06-11 04:07:29 +08:00
|
|
|
// This file defines several CodeGen-specific LLVM IR analysis utilities.
|
2010-04-21 09:22:34 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2014-06-11 04:39:35 +08:00
|
|
|
#include "llvm/CodeGen/Analysis.h"
|
2014-06-26 06:36:37 +08:00
|
|
|
#include "llvm/Analysis/ValueTracking.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
2017-11-08 09:01:31 +08:00
|
|
|
#include "llvm/CodeGen/TargetInstrInfo.h"
|
2017-11-17 09:07:10 +08:00
|
|
|
#include "llvm/CodeGen/TargetLowering.h"
|
|
|
|
#include "llvm/CodeGen/TargetSubtargetInfo.h"
|
2013-01-02 19:36:10 +08:00
|
|
|
#include "llvm/IR/DataLayout.h"
|
|
|
|
#include "llvm/IR/DerivedTypes.h"
|
|
|
|
#include "llvm/IR/Function.h"
|
|
|
|
#include "llvm/IR/Instructions.h"
|
|
|
|
#include "llvm/IR/IntrinsicInst.h"
|
|
|
|
#include "llvm/IR/Module.h"
|
2010-04-21 09:22:34 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2020-05-24 02:49:38 +08:00
|
|
|
#include "llvm/Target/TargetMachine.h"
|
2014-08-05 05:25:23 +08:00
|
|
|
|
2010-04-21 09:22:34 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
2015-01-14 13:33:01 +08:00
|
|
|
/// Compute the linearized index of a member in a nested aggregate/struct/array
|
|
|
|
/// by recursing and accumulating CurIndex as long as there are indices in the
|
|
|
|
/// index list.
|
2011-07-18 12:54:35 +08:00
|
|
|
unsigned llvm::ComputeLinearIndex(Type *Ty,
|
2010-04-21 09:22:34 +08:00
|
|
|
const unsigned *Indices,
|
|
|
|
const unsigned *IndicesEnd,
|
|
|
|
unsigned CurIndex) {
|
|
|
|
// Base case: We're done.
|
|
|
|
if (Indices && Indices == IndicesEnd)
|
|
|
|
return CurIndex;
|
|
|
|
|
|
|
|
// Given a struct type, recursively traverse the elements.
|
2011-07-18 12:54:35 +08:00
|
|
|
if (StructType *STy = dyn_cast<StructType>(Ty)) {
|
2021-02-22 11:58:07 +08:00
|
|
|
for (auto I : llvm::enumerate(STy->elements())) {
|
|
|
|
Type *ET = I.value();
|
|
|
|
if (Indices && *Indices == I.index())
|
|
|
|
return ComputeLinearIndex(ET, Indices + 1, IndicesEnd, CurIndex);
|
|
|
|
CurIndex = ComputeLinearIndex(ET, nullptr, nullptr, CurIndex);
|
2010-04-21 09:22:34 +08:00
|
|
|
}
|
2015-01-14 13:38:48 +08:00
|
|
|
assert(!Indices && "Unexpected out of bound");
|
2010-04-21 09:22:34 +08:00
|
|
|
return CurIndex;
|
|
|
|
}
|
|
|
|
// Given an array type, recursively traverse the elements.
|
2011-07-18 12:54:35 +08:00
|
|
|
else if (ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
|
|
|
|
Type *EltTy = ATy->getElementType();
|
2015-01-14 13:33:01 +08:00
|
|
|
unsigned NumElts = ATy->getNumElements();
|
|
|
|
// Compute the Linear offset when jumping one element of the array
|
|
|
|
unsigned EltLinearOffset = ComputeLinearIndex(EltTy, nullptr, nullptr, 0);
|
2015-01-14 13:38:48 +08:00
|
|
|
if (Indices) {
|
|
|
|
assert(*Indices < NumElts && "Unexpected out of bound");
|
2015-01-14 13:33:01 +08:00
|
|
|
// If the indice is inside the array, compute the index to the requested
|
|
|
|
// elt and recurse inside the element with the end of the indices list
|
|
|
|
CurIndex += EltLinearOffset* *Indices;
|
|
|
|
return ComputeLinearIndex(EltTy, Indices+1, IndicesEnd, CurIndex);
|
2010-04-21 09:22:34 +08:00
|
|
|
}
|
2015-01-14 13:33:01 +08:00
|
|
|
CurIndex += EltLinearOffset*NumElts;
|
2010-04-21 09:22:34 +08:00
|
|
|
return CurIndex;
|
|
|
|
}
|
|
|
|
// We haven't found the type we're looking for, so keep searching.
|
|
|
|
return CurIndex + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ComputeValueVTs - Given an LLVM IR type, compute a sequence of
|
|
|
|
/// EVTs that represent all the individual underlying
|
|
|
|
/// non-aggregate types that comprise it.
|
|
|
|
///
|
|
|
|
/// If Offsets is non-null, it points to a vector to be filled in
|
|
|
|
/// with the in-memory offsets of each of the individual values.
|
|
|
|
///
|
2015-07-09 09:57:34 +08:00
|
|
|
void llvm::ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL,
|
|
|
|
Type *Ty, SmallVectorImpl<EVT> &ValueVTs,
|
2019-05-01 20:37:30 +08:00
|
|
|
SmallVectorImpl<EVT> *MemVTs,
|
2010-04-21 09:22:34 +08:00
|
|
|
SmallVectorImpl<uint64_t> *Offsets,
|
|
|
|
uint64_t StartingOffset) {
|
|
|
|
// Given a struct type, recursively traverse the elements.
|
2011-07-18 12:54:35 +08:00
|
|
|
if (StructType *STy = dyn_cast<StructType>(Ty)) {
|
2021-01-18 15:29:43 +08:00
|
|
|
// If the Offsets aren't needed, don't query the struct layout. This allows
|
|
|
|
// us to support structs with scalable vectors for operations that don't
|
|
|
|
// need offsets.
|
|
|
|
const StructLayout *SL = Offsets ? DL.getStructLayout(STy) : nullptr;
|
2010-04-21 09:22:34 +08:00
|
|
|
for (StructType::element_iterator EB = STy->element_begin(),
|
|
|
|
EI = EB,
|
|
|
|
EE = STy->element_end();
|
2021-01-18 15:29:43 +08:00
|
|
|
EI != EE; ++EI) {
|
|
|
|
// Don't compute the element offset if we didn't get a StructLayout above.
|
|
|
|
uint64_t EltOffset = SL ? SL->getElementOffset(EI - EB) : 0;
|
2019-05-01 20:37:30 +08:00
|
|
|
ComputeValueVTs(TLI, DL, *EI, ValueVTs, MemVTs, Offsets,
|
2021-01-18 15:29:43 +08:00
|
|
|
StartingOffset + EltOffset);
|
|
|
|
}
|
2010-04-21 09:22:34 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Given an array type, recursively traverse the elements.
|
2011-07-18 12:54:35 +08:00
|
|
|
if (ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
|
|
|
|
Type *EltTy = ATy->getElementType();
|
2021-01-18 15:29:43 +08:00
|
|
|
uint64_t EltSize = DL.getTypeAllocSize(EltTy).getFixedValue();
|
2010-04-21 09:22:34 +08:00
|
|
|
for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i)
|
2019-05-01 20:37:30 +08:00
|
|
|
ComputeValueVTs(TLI, DL, EltTy, ValueVTs, MemVTs, Offsets,
|
2010-04-21 09:22:34 +08:00
|
|
|
StartingOffset + i * EltSize);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Interpret void as zero return values.
|
|
|
|
if (Ty->isVoidTy())
|
|
|
|
return;
|
|
|
|
// Base case: we can get an EVT for this LLVM IR type.
|
2015-07-09 10:09:04 +08:00
|
|
|
ValueVTs.push_back(TLI.getValueType(DL, Ty));
|
2019-05-01 20:37:30 +08:00
|
|
|
if (MemVTs)
|
|
|
|
MemVTs->push_back(TLI.getMemValueType(DL, Ty));
|
2010-04-21 09:22:34 +08:00
|
|
|
if (Offsets)
|
|
|
|
Offsets->push_back(StartingOffset);
|
|
|
|
}
|
|
|
|
|
2019-05-01 20:37:30 +08:00
|
|
|
void llvm::ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL,
|
|
|
|
Type *Ty, SmallVectorImpl<EVT> &ValueVTs,
|
|
|
|
SmallVectorImpl<uint64_t> *Offsets,
|
|
|
|
uint64_t StartingOffset) {
|
|
|
|
return ComputeValueVTs(TLI, DL, Ty, ValueVTs, /*MemVTs=*/nullptr, Offsets,
|
|
|
|
StartingOffset);
|
|
|
|
}
|
|
|
|
|
2019-04-11 01:27:56 +08:00
|
|
|
void llvm::computeValueLLTs(const DataLayout &DL, Type &Ty,
|
|
|
|
SmallVectorImpl<LLT> &ValueTys,
|
|
|
|
SmallVectorImpl<uint64_t> *Offsets,
|
|
|
|
uint64_t StartingOffset) {
|
|
|
|
// Given a struct type, recursively traverse the elements.
|
|
|
|
if (StructType *STy = dyn_cast<StructType>(&Ty)) {
|
2021-01-18 15:29:43 +08:00
|
|
|
// If the Offsets aren't needed, don't query the struct layout. This allows
|
|
|
|
// us to support structs with scalable vectors for operations that don't
|
|
|
|
// need offsets.
|
|
|
|
const StructLayout *SL = Offsets ? DL.getStructLayout(STy) : nullptr;
|
|
|
|
for (unsigned I = 0, E = STy->getNumElements(); I != E; ++I) {
|
|
|
|
uint64_t EltOffset = SL ? SL->getElementOffset(I) : 0;
|
2019-04-11 01:27:56 +08:00
|
|
|
computeValueLLTs(DL, *STy->getElementType(I), ValueTys, Offsets,
|
2021-01-18 15:29:43 +08:00
|
|
|
StartingOffset + EltOffset);
|
|
|
|
}
|
2019-04-11 01:27:56 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Given an array type, recursively traverse the elements.
|
|
|
|
if (ArrayType *ATy = dyn_cast<ArrayType>(&Ty)) {
|
|
|
|
Type *EltTy = ATy->getElementType();
|
2021-01-18 15:29:43 +08:00
|
|
|
uint64_t EltSize = DL.getTypeAllocSize(EltTy).getFixedValue();
|
2019-04-11 01:27:56 +08:00
|
|
|
for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i)
|
|
|
|
computeValueLLTs(DL, *EltTy, ValueTys, Offsets,
|
|
|
|
StartingOffset + i * EltSize);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Interpret void as zero return values.
|
|
|
|
if (Ty.isVoidTy())
|
|
|
|
return;
|
|
|
|
// Base case: we can get an LLT for this LLVM IR type.
|
|
|
|
ValueTys.push_back(getLLTForType(Ty, DL));
|
|
|
|
if (Offsets != nullptr)
|
|
|
|
Offsets->push_back(StartingOffset * 8);
|
|
|
|
}
|
|
|
|
|
2010-04-21 09:22:34 +08:00
|
|
|
/// ExtractTypeInfo - Returns the type info, possibly bitcast, encoded in V.
|
2014-11-14 08:35:50 +08:00
|
|
|
GlobalValue *llvm::ExtractTypeInfo(Value *V) {
|
2019-08-23 03:56:14 +08:00
|
|
|
V = V->stripPointerCasts();
|
2014-11-14 08:35:50 +08:00
|
|
|
GlobalValue *GV = dyn_cast<GlobalValue>(V);
|
|
|
|
GlobalVariable *Var = dyn_cast<GlobalVariable>(V);
|
2010-04-21 09:22:34 +08:00
|
|
|
|
2014-11-14 08:35:50 +08:00
|
|
|
if (Var && Var->getName() == "llvm.eh.catch.all.value") {
|
|
|
|
assert(Var->hasInitializer() &&
|
2010-04-21 09:22:34 +08:00
|
|
|
"The EH catch-all value must have an initializer");
|
2014-11-14 08:35:50 +08:00
|
|
|
Value *Init = Var->getInitializer();
|
|
|
|
GV = dyn_cast<GlobalValue>(Init);
|
2010-04-21 09:22:34 +08:00
|
|
|
if (!GV) V = cast<ConstantPointerNull>(Init);
|
|
|
|
}
|
|
|
|
|
|
|
|
assert((GV || isa<ConstantPointerNull>(V)) &&
|
|
|
|
"TypeInfo must be a global variable or NULL");
|
|
|
|
return GV;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// getFCmpCondCode - Return the ISD condition code corresponding to
|
|
|
|
/// the given LLVM IR floating-point condition code. This includes
|
|
|
|
/// consideration of global floating-point math flags.
|
|
|
|
///
|
|
|
|
ISD::CondCode llvm::getFCmpCondCode(FCmpInst::Predicate Pred) {
|
|
|
|
switch (Pred) {
|
2011-12-03 06:16:29 +08:00
|
|
|
case FCmpInst::FCMP_FALSE: return ISD::SETFALSE;
|
|
|
|
case FCmpInst::FCMP_OEQ: return ISD::SETOEQ;
|
|
|
|
case FCmpInst::FCMP_OGT: return ISD::SETOGT;
|
|
|
|
case FCmpInst::FCMP_OGE: return ISD::SETOGE;
|
|
|
|
case FCmpInst::FCMP_OLT: return ISD::SETOLT;
|
|
|
|
case FCmpInst::FCMP_OLE: return ISD::SETOLE;
|
|
|
|
case FCmpInst::FCMP_ONE: return ISD::SETONE;
|
|
|
|
case FCmpInst::FCMP_ORD: return ISD::SETO;
|
|
|
|
case FCmpInst::FCMP_UNO: return ISD::SETUO;
|
|
|
|
case FCmpInst::FCMP_UEQ: return ISD::SETUEQ;
|
|
|
|
case FCmpInst::FCMP_UGT: return ISD::SETUGT;
|
|
|
|
case FCmpInst::FCMP_UGE: return ISD::SETUGE;
|
|
|
|
case FCmpInst::FCMP_ULT: return ISD::SETULT;
|
|
|
|
case FCmpInst::FCMP_ULE: return ISD::SETULE;
|
|
|
|
case FCmpInst::FCMP_UNE: return ISD::SETUNE;
|
|
|
|
case FCmpInst::FCMP_TRUE: return ISD::SETTRUE;
|
2012-01-21 05:51:11 +08:00
|
|
|
default: llvm_unreachable("Invalid FCmp predicate opcode!");
|
2011-12-03 06:16:29 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ISD::CondCode llvm::getFCmpCodeWithoutNaN(ISD::CondCode CC) {
|
|
|
|
switch (CC) {
|
|
|
|
case ISD::SETOEQ: case ISD::SETUEQ: return ISD::SETEQ;
|
|
|
|
case ISD::SETONE: case ISD::SETUNE: return ISD::SETNE;
|
|
|
|
case ISD::SETOLT: case ISD::SETULT: return ISD::SETLT;
|
|
|
|
case ISD::SETOLE: case ISD::SETULE: return ISD::SETLE;
|
|
|
|
case ISD::SETOGT: case ISD::SETUGT: return ISD::SETGT;
|
|
|
|
case ISD::SETOGE: case ISD::SETUGE: return ISD::SETGE;
|
2012-01-21 05:51:11 +08:00
|
|
|
default: return CC;
|
2010-04-21 09:22:34 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ISD::CondCode llvm::getICmpCondCode(ICmpInst::Predicate Pred) {
|
|
|
|
switch (Pred) {
|
|
|
|
case ICmpInst::ICMP_EQ: return ISD::SETEQ;
|
|
|
|
case ICmpInst::ICMP_NE: return ISD::SETNE;
|
|
|
|
case ICmpInst::ICMP_SLE: return ISD::SETLE;
|
|
|
|
case ICmpInst::ICMP_ULE: return ISD::SETULE;
|
|
|
|
case ICmpInst::ICMP_SGE: return ISD::SETGE;
|
|
|
|
case ICmpInst::ICMP_UGE: return ISD::SETUGE;
|
|
|
|
case ICmpInst::ICMP_SLT: return ISD::SETLT;
|
|
|
|
case ICmpInst::ICMP_ULT: return ISD::SETULT;
|
|
|
|
case ICmpInst::ICMP_SGT: return ISD::SETGT;
|
|
|
|
case ICmpInst::ICMP_UGT: return ISD::SETUGT;
|
|
|
|
default:
|
|
|
|
llvm_unreachable("Invalid ICmp predicate opcode!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-30 22:36:23 +08:00
|
|
|
ICmpInst::Predicate llvm::getICmpCondCode(ISD::CondCode Pred) {
|
|
|
|
switch (Pred) {
|
|
|
|
case ISD::SETEQ:
|
|
|
|
return ICmpInst::ICMP_EQ;
|
|
|
|
case ISD::SETNE:
|
|
|
|
return ICmpInst::ICMP_NE;
|
|
|
|
case ISD::SETLE:
|
|
|
|
return ICmpInst::ICMP_SLE;
|
|
|
|
case ISD::SETULE:
|
|
|
|
return ICmpInst::ICMP_ULE;
|
|
|
|
case ISD::SETGE:
|
|
|
|
return ICmpInst::ICMP_SGE;
|
|
|
|
case ISD::SETUGE:
|
|
|
|
return ICmpInst::ICMP_UGE;
|
|
|
|
case ISD::SETLT:
|
|
|
|
return ICmpInst::ICMP_SLT;
|
|
|
|
case ISD::SETULT:
|
|
|
|
return ICmpInst::ICMP_ULT;
|
|
|
|
case ISD::SETGT:
|
|
|
|
return ICmpInst::ICMP_SGT;
|
|
|
|
case ISD::SETUGT:
|
|
|
|
return ICmpInst::ICMP_UGT;
|
|
|
|
default:
|
|
|
|
llvm_unreachable("Invalid ISD integer condition code!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-20 12:27:51 +08:00
|
|
|
static bool isNoopBitcast(Type *T1, Type *T2,
|
2013-07-23 05:05:47 +08:00
|
|
|
const TargetLoweringBase& TLI) {
|
2013-04-20 12:27:51 +08:00
|
|
|
return T1 == T2 || (T1->isPointerTy() && T2->isPointerTy()) ||
|
|
|
|
(isa<VectorType>(T1) && isa<VectorType>(T2) &&
|
|
|
|
TLI.isTypeLegal(EVT::getEVT(T1)) && TLI.isTypeLegal(EVT::getEVT(T2)));
|
|
|
|
}
|
2012-06-01 13:01:15 +08:00
|
|
|
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
/// Look through operations that will be free to find the earliest source of
|
|
|
|
/// this value.
|
|
|
|
///
|
2020-01-06 18:15:44 +08:00
|
|
|
/// @param ValLoc If V has aggregate type, we will be interested in a particular
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
/// scalar component. This records its address; the reverse of this list gives a
|
|
|
|
/// sequence of indices appropriate for an extractvalue to locate the important
|
|
|
|
/// value. This value is updated during the function and on exit will indicate
|
|
|
|
/// similar information for the Value returned.
|
|
|
|
///
|
|
|
|
/// @param DataBits If this function looks through truncate instructions, this
|
|
|
|
/// will record the smallest size attained.
|
|
|
|
static const Value *getNoopInput(const Value *V,
|
|
|
|
SmallVectorImpl<unsigned> &ValLoc,
|
|
|
|
unsigned &DataBits,
|
2015-07-09 10:09:04 +08:00
|
|
|
const TargetLoweringBase &TLI,
|
|
|
|
const DataLayout &DL) {
|
2013-04-20 12:27:51 +08:00
|
|
|
while (true) {
|
|
|
|
// Try to look through V1; if V1 is not an instruction, it can't be looked
|
|
|
|
// through.
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
const Instruction *I = dyn_cast<Instruction>(V);
|
|
|
|
if (!I || I->getNumOperands() == 0) return V;
|
2014-04-14 08:51:57 +08:00
|
|
|
const Value *NoopInput = nullptr;
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
|
|
|
|
Value *Op = I->getOperand(0);
|
|
|
|
if (isa<BitCastInst>(I)) {
|
|
|
|
// Look through truly no-op bitcasts.
|
|
|
|
if (isNoopBitcast(Op->getType(), I->getType(), TLI))
|
|
|
|
NoopInput = Op;
|
|
|
|
} else if (isa<GetElementPtrInst>(I)) {
|
|
|
|
// Look through getelementptr
|
|
|
|
if (cast<GetElementPtrInst>(I)->hasAllZeroIndices())
|
|
|
|
NoopInput = Op;
|
|
|
|
} else if (isa<IntToPtrInst>(I)) {
|
|
|
|
// Look through inttoptr.
|
|
|
|
// Make sure this isn't a truncating or extending cast. We could
|
|
|
|
// support this eventually, but don't bother for now.
|
|
|
|
if (!isa<VectorType>(I->getType()) &&
|
2015-07-09 10:09:04 +08:00
|
|
|
DL.getPointerSizeInBits() ==
|
|
|
|
cast<IntegerType>(Op->getType())->getBitWidth())
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
NoopInput = Op;
|
|
|
|
} else if (isa<PtrToIntInst>(I)) {
|
|
|
|
// Look through ptrtoint.
|
|
|
|
// Make sure this isn't a truncating or extending cast. We could
|
|
|
|
// support this eventually, but don't bother for now.
|
|
|
|
if (!isa<VectorType>(I->getType()) &&
|
2015-07-09 10:09:04 +08:00
|
|
|
DL.getPointerSizeInBits() ==
|
|
|
|
cast<IntegerType>(I->getType())->getBitWidth())
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
NoopInput = Op;
|
|
|
|
} else if (isa<TruncInst>(I) &&
|
|
|
|
TLI.allowTruncateForTailCall(Op->getType(), I->getType())) {
|
2019-10-08 20:53:54 +08:00
|
|
|
DataBits = std::min((uint64_t)DataBits,
|
|
|
|
I->getType()->getPrimitiveSizeInBits().getFixedSize());
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
NoopInput = Op;
|
2020-04-13 14:47:17 +08:00
|
|
|
} else if (auto *CB = dyn_cast<CallBase>(I)) {
|
|
|
|
const Value *ReturnedOp = CB->getReturnedArgOperand();
|
2017-01-04 04:33:22 +08:00
|
|
|
if (ReturnedOp && isNoopBitcast(ReturnedOp->getType(), I->getType(), TLI))
|
|
|
|
NoopInput = ReturnedOp;
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
} else if (const InsertValueInst *IVI = dyn_cast<InsertValueInst>(V)) {
|
|
|
|
// Value may come from either the aggregate or the scalar
|
|
|
|
ArrayRef<unsigned> InsertLoc = IVI->getIndices();
|
2015-05-07 04:07:38 +08:00
|
|
|
if (ValLoc.size() >= InsertLoc.size() &&
|
|
|
|
std::equal(InsertLoc.begin(), InsertLoc.end(), ValLoc.rbegin())) {
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
// The type being inserted is a nested sub-type of the aggregate; we
|
|
|
|
// have to remove those initial indices to get the location we're
|
|
|
|
// interested in for the operand.
|
|
|
|
ValLoc.resize(ValLoc.size() - InsertLoc.size());
|
|
|
|
NoopInput = IVI->getInsertedValueOperand();
|
|
|
|
} else {
|
|
|
|
// The struct we're inserting into has the value we're interested in, no
|
|
|
|
// change of address.
|
|
|
|
NoopInput = Op;
|
|
|
|
}
|
|
|
|
} else if (const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(V)) {
|
|
|
|
// The part we're interested in will inevitably be some sub-section of the
|
|
|
|
// previous aggregate. Combine the two paths to obtain the true address of
|
|
|
|
// our element.
|
|
|
|
ArrayRef<unsigned> ExtractLoc = EVI->getIndices();
|
2015-02-28 18:11:12 +08:00
|
|
|
ValLoc.append(ExtractLoc.rbegin(), ExtractLoc.rend());
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
NoopInput = Op;
|
2013-04-20 12:27:51 +08:00
|
|
|
}
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
// Terminate if we couldn't find anything to look through.
|
|
|
|
if (!NoopInput)
|
|
|
|
return V;
|
2012-06-01 13:16:33 +08:00
|
|
|
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
V = NoopInput;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Return true if this scalar return value only has bits discarded on its path
|
|
|
|
/// from the "tail call" to the "ret". This includes the obvious noop
|
|
|
|
/// instructions handled by getNoopInput above as well as free truncations (or
|
|
|
|
/// extensions prior to the call).
|
|
|
|
static bool slotOnlyDiscardsData(const Value *RetVal, const Value *CallVal,
|
|
|
|
SmallVectorImpl<unsigned> &RetIndices,
|
|
|
|
SmallVectorImpl<unsigned> &CallIndices,
|
2013-08-12 17:45:46 +08:00
|
|
|
bool AllowDifferingSizes,
|
2015-07-09 10:09:04 +08:00
|
|
|
const TargetLoweringBase &TLI,
|
|
|
|
const DataLayout &DL) {
|
2012-06-01 13:16:33 +08:00
|
|
|
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
// Trace the sub-value needed by the return value as far back up the graph as
|
|
|
|
// possible, in the hope that it will intersect with the value produced by the
|
|
|
|
// call. In the simple case with no "returned" attribute, the hope is actually
|
|
|
|
// that we end up back at the tail call instruction itself.
|
|
|
|
unsigned BitsRequired = UINT_MAX;
|
2015-07-09 10:09:04 +08:00
|
|
|
RetVal = getNoopInput(RetVal, RetIndices, BitsRequired, TLI, DL);
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
|
|
|
|
// If this slot in the value returned is undef, it doesn't matter what the
|
|
|
|
// call puts there, it'll be fine.
|
|
|
|
if (isa<UndefValue>(RetVal))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Now do a similar search up through the graph to find where the value
|
|
|
|
// actually returned by the "tail call" comes from. In the simple case without
|
|
|
|
// a "returned" attribute, the search will be blocked immediately and the loop
|
|
|
|
// a Noop.
|
|
|
|
unsigned BitsProvided = UINT_MAX;
|
2015-07-09 10:09:04 +08:00
|
|
|
CallVal = getNoopInput(CallVal, CallIndices, BitsProvided, TLI, DL);
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
|
|
|
|
// There's no hope if we can't actually trace them to (the same part of!) the
|
|
|
|
// same value.
|
|
|
|
if (CallVal != RetVal || CallIndices != RetIndices)
|
|
|
|
return false;
|
2013-04-20 12:27:51 +08:00
|
|
|
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
// However, intervening truncates may have made the call non-tail. Make sure
|
|
|
|
// all the bits that are needed by the "ret" have been provided by the "tail
|
|
|
|
// call". FIXME: with sufficiently cunning bit-tracking, we could look through
|
|
|
|
// extensions too.
|
2013-08-12 17:45:46 +08:00
|
|
|
if (BitsProvided < BitsRequired ||
|
|
|
|
(!AllowDifferingSizes && BitsProvided != BitsRequired))
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// For an aggregate type, determine whether a given index is within bounds or
|
|
|
|
/// not.
|
2020-03-04 07:42:16 +08:00
|
|
|
static bool indexReallyValid(Type *T, unsigned Idx) {
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
if (ArrayType *AT = dyn_cast<ArrayType>(T))
|
|
|
|
return Idx < AT->getNumElements();
|
|
|
|
|
|
|
|
return Idx < cast<StructType>(T)->getNumElements();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Move the given iterators to the next leaf type in depth first traversal.
|
|
|
|
///
|
|
|
|
/// Performs a depth-first traversal of the type as specified by its arguments,
|
|
|
|
/// stopping at the next leaf node (which may be a legitimate scalar type or an
|
|
|
|
/// empty struct or array).
|
|
|
|
///
|
|
|
|
/// @param SubTypes List of the partial components making up the type from
|
|
|
|
/// outermost to innermost non-empty aggregate. The element currently
|
|
|
|
/// represented is SubTypes.back()->getTypeAtIndex(Path.back() - 1).
|
|
|
|
///
|
|
|
|
/// @param Path Set of extractvalue indices leading from the outermost type
|
|
|
|
/// (SubTypes[0]) to the leaf node currently represented.
|
|
|
|
///
|
|
|
|
/// @returns true if a new type was found, false otherwise. Calling this
|
|
|
|
/// function again on a finished iterator will repeatedly return
|
|
|
|
/// false. SubTypes.back()->getTypeAtIndex(Path.back()) is either an empty
|
|
|
|
/// aggregate or a non-aggregate
|
2020-03-04 07:42:16 +08:00
|
|
|
static bool advanceToNextLeafType(SmallVectorImpl<Type *> &SubTypes,
|
2013-08-09 22:44:41 +08:00
|
|
|
SmallVectorImpl<unsigned> &Path) {
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
// First march back up the tree until we can successfully increment one of the
|
|
|
|
// coordinates in Path.
|
|
|
|
while (!Path.empty() && !indexReallyValid(SubTypes.back(), Path.back() + 1)) {
|
|
|
|
Path.pop_back();
|
|
|
|
SubTypes.pop_back();
|
2012-06-01 13:16:33 +08:00
|
|
|
}
|
|
|
|
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
// If we reached the top, then the iterator is done.
|
|
|
|
if (Path.empty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// We know there's *some* valid leaf now, so march back down the tree picking
|
|
|
|
// out the left-most element at each node.
|
|
|
|
++Path.back();
|
2020-03-04 07:42:16 +08:00
|
|
|
Type *DeeperType =
|
|
|
|
ExtractValueInst::getIndexedType(SubTypes.back(), Path.back());
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
while (DeeperType->isAggregateType()) {
|
2020-03-04 07:42:16 +08:00
|
|
|
if (!indexReallyValid(DeeperType, 0))
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
return true;
|
|
|
|
|
2020-03-04 07:42:16 +08:00
|
|
|
SubTypes.push_back(DeeperType);
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
Path.push_back(0);
|
2012-06-01 13:01:15 +08:00
|
|
|
|
2020-03-04 07:42:16 +08:00
|
|
|
DeeperType = ExtractValueInst::getIndexedType(DeeperType, 0);
|
2013-04-20 12:27:51 +08:00
|
|
|
}
|
2012-06-01 13:01:15 +08:00
|
|
|
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Find the first non-empty, scalar-like type in Next and setup the iterator
|
|
|
|
/// components.
|
|
|
|
///
|
|
|
|
/// Assuming Next is an aggregate of some kind, this function will traverse the
|
|
|
|
/// tree from left to right (i.e. depth-first) looking for the first
|
|
|
|
/// non-aggregate type which will play a role in function return.
|
|
|
|
///
|
|
|
|
/// For example, if Next was {[0 x i64], {{}, i32, {}}, i32} then we would setup
|
|
|
|
/// Path as [1, 1] and SubTypes as [Next, {{}, i32, {}}] to represent the first
|
|
|
|
/// i32 in that type.
|
2020-03-04 07:42:16 +08:00
|
|
|
static bool firstRealType(Type *Next, SmallVectorImpl<Type *> &SubTypes,
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
SmallVectorImpl<unsigned> &Path) {
|
|
|
|
// First initialise the iterator components to the first "leaf" node
|
|
|
|
// (i.e. node with no valid sub-type at any index, so {} does count as a leaf
|
|
|
|
// despite nominally being an aggregate).
|
2020-03-04 07:42:16 +08:00
|
|
|
while (Type *FirstInner = ExtractValueInst::getIndexedType(Next, 0)) {
|
|
|
|
SubTypes.push_back(Next);
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
Path.push_back(0);
|
2020-03-04 07:42:16 +08:00
|
|
|
Next = FirstInner;
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// If there's no Path now, Next was originally scalar already (or empty
|
|
|
|
// leaf). We're done.
|
|
|
|
if (Path.empty())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Otherwise, use normal iteration to keep looking through the tree until we
|
|
|
|
// find a non-aggregate type.
|
2020-03-04 07:42:16 +08:00
|
|
|
while (ExtractValueInst::getIndexedType(SubTypes.back(), Path.back())
|
|
|
|
->isAggregateType()) {
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
if (!advanceToNextLeafType(SubTypes, Path))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Set the iterator data-structures to the next non-empty, non-aggregate
|
|
|
|
/// subtype.
|
2020-03-04 07:42:16 +08:00
|
|
|
static bool nextRealType(SmallVectorImpl<Type *> &SubTypes,
|
2013-08-09 22:44:41 +08:00
|
|
|
SmallVectorImpl<unsigned> &Path) {
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
do {
|
|
|
|
if (!advanceToNextLeafType(SubTypes, Path))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
assert(!Path.empty() && "found a leaf but didn't set the path?");
|
2020-03-04 07:42:16 +08:00
|
|
|
} while (ExtractValueInst::getIndexedType(SubTypes.back(), Path.back())
|
|
|
|
->isAggregateType());
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
|
|
|
|
return true;
|
2013-04-20 12:27:51 +08:00
|
|
|
}
|
2012-06-01 13:01:15 +08:00
|
|
|
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
|
2010-04-21 09:22:34 +08:00
|
|
|
/// Test if the given instruction is in a position to be optimized
|
|
|
|
/// with a tail-call. This roughly means that it's in a block with
|
|
|
|
/// a return and there's nothing that needs to be scheduled
|
|
|
|
/// between it and the return.
|
|
|
|
///
|
|
|
|
/// This function only tests target-independent requirements.
|
2020-04-14 14:04:52 +08:00
|
|
|
bool llvm::isInTailCallPosition(const CallBase &Call, const TargetMachine &TM) {
|
|
|
|
const BasicBlock *ExitBB = Call.getParent();
|
2018-10-15 18:04:59 +08:00
|
|
|
const Instruction *Term = ExitBB->getTerminator();
|
2010-04-21 09:22:34 +08:00
|
|
|
const ReturnInst *Ret = dyn_cast<ReturnInst>(Term);
|
|
|
|
|
|
|
|
// The block must end in a return statement or unreachable.
|
|
|
|
//
|
|
|
|
// FIXME: Decline tailcall if it's not guaranteed and if the block ends in
|
|
|
|
// an unreachable, for now. The way tailcall optimization is currently
|
|
|
|
// implemented means it will add an epilogue followed by a jump. That is
|
|
|
|
// not profitable. Also, if the callee is a special function (e.g.
|
|
|
|
// longjmp on x86), it can end up causing miscompilation that has not
|
|
|
|
// been fully understood.
|
2020-11-19 20:32:50 +08:00
|
|
|
if (!Ret && ((!TM.Options.GuaranteedTailCallOpt &&
|
|
|
|
Call.getCallingConv() != CallingConv::Tail &&
|
|
|
|
Call.getCallingConv() != CallingConv::SwiftTail) ||
|
|
|
|
!isa<UnreachableInst>(Term)))
|
2012-06-01 13:01:15 +08:00
|
|
|
return false;
|
2010-04-21 09:22:34 +08:00
|
|
|
|
|
|
|
// If I will have a chain, make sure no other instruction that will have a
|
|
|
|
// chain interposes between I and the return.
|
2020-06-03 23:37:07 +08:00
|
|
|
// Check for all calls including speculatable functions.
|
|
|
|
for (BasicBlock::const_iterator BBI = std::prev(ExitBB->end(), 2);; --BBI) {
|
|
|
|
if (&*BBI == &Call)
|
|
|
|
break;
|
|
|
|
// Debug info intrinsics do not get in the way of tail call optimization.
|
[CSSPGO] IR intrinsic for pseudo-probe block instrumentation
This change introduces a new IR intrinsic named `llvm.pseudoprobe` for pseudo-probe block instrumentation. Please refer to https://reviews.llvm.org/D86193 for the whole story.
A pseudo probe is used to collect the execution count of the block where the probe is instrumented. This requires a pseudo probe to be persisting. The LLVM PGO instrumentation also instruments in similar places by placing a counter in the form of atomic read/write operations or runtime helper calls. While these operations are very persisting or optimization-resilient, in theory we can borrow the atomic read/write implementation from PGO counters and cut it off at the end of compilation with all the atomics converted into binary data. This was our initial design and we’ve seen promising sample correlation quality with it. However, the atomics approach has a couple issues:
1. IR Optimizations are blocked unexpectedly. Those atomic instructions are not going to be physically present in the binary code, but since they are on the IR till very end of compilation, they can still prevent certain IR optimizations and result in lower code quality.
2. The counter atomics may not be fully cleaned up from the code stream eventually.
3. Extra work is needed for re-targeting.
We choose to implement pseudo probes based on a special LLVM intrinsic, which is expected to have most of the semantics that comes with an atomic operation but does not block desired optimizations as much as possible. More specifically the semantics associated with the new intrinsic enforces a pseudo probe to be virtually executed exactly the same number of times before and after an IR optimization. The intrinsic also comes with certain flags that are carefully chosen so that the places they are probing are not going to be messed up by the optimizer while most of the IR optimizations still work. The core flags given to the special intrinsic is `IntrInaccessibleMemOnly`, which means the intrinsic accesses memory and does have a side effect so that it is not removable, but is does not access memory locations that are accessible by any original instructions. This way the intrinsic does not alias with any original instruction and thus it does not block optimizations as much as an atomic operation does. We also assign a function GUID and a block index to an intrinsic so that they are uniquely identified and not merged in order to achieve good correlation quality.
Let's now look at an example. Given the following LLVM IR:
```
define internal void @foo2(i32 %x, void (i32)* %f) !dbg !4 {
bb0:
%cmp = icmp eq i32 %x, 0
br i1 %cmp, label %bb1, label %bb2
bb1:
br label %bb3
bb2:
br label %bb3
bb3:
ret void
}
```
The instrumented IR will look like below. Note that each `llvm.pseudoprobe` intrinsic call represents a pseudo probe at a block, of which the first parameter is the GUID of the probe’s owner function and the second parameter is the probe’s ID.
```
define internal void @foo2(i32 %x, void (i32)* %f) !dbg !4 {
bb0:
%cmp = icmp eq i32 %x, 0
call void @llvm.pseudoprobe(i64 837061429793323041, i64 1)
br i1 %cmp, label %bb1, label %bb2
bb1:
call void @llvm.pseudoprobe(i64 837061429793323041, i64 2)
br label %bb3
bb2:
call void @llvm.pseudoprobe(i64 837061429793323041, i64 3)
br label %bb3
bb3:
call void @llvm.pseudoprobe(i64 837061429793323041, i64 4)
ret void
}
```
Reviewed By: wmi
Differential Revision: https://reviews.llvm.org/D86490
2020-11-19 04:42:51 +08:00
|
|
|
// Pseudo probe intrinsics do not block tail call optimization either.
|
2021-10-01 00:13:41 +08:00
|
|
|
if (BBI->isDebugOrPseudoInst())
|
[CSSPGO] IR intrinsic for pseudo-probe block instrumentation
This change introduces a new IR intrinsic named `llvm.pseudoprobe` for pseudo-probe block instrumentation. Please refer to https://reviews.llvm.org/D86193 for the whole story.
A pseudo probe is used to collect the execution count of the block where the probe is instrumented. This requires a pseudo probe to be persisting. The LLVM PGO instrumentation also instruments in similar places by placing a counter in the form of atomic read/write operations or runtime helper calls. While these operations are very persisting or optimization-resilient, in theory we can borrow the atomic read/write implementation from PGO counters and cut it off at the end of compilation with all the atomics converted into binary data. This was our initial design and we’ve seen promising sample correlation quality with it. However, the atomics approach has a couple issues:
1. IR Optimizations are blocked unexpectedly. Those atomic instructions are not going to be physically present in the binary code, but since they are on the IR till very end of compilation, they can still prevent certain IR optimizations and result in lower code quality.
2. The counter atomics may not be fully cleaned up from the code stream eventually.
3. Extra work is needed for re-targeting.
We choose to implement pseudo probes based on a special LLVM intrinsic, which is expected to have most of the semantics that comes with an atomic operation but does not block desired optimizations as much as possible. More specifically the semantics associated with the new intrinsic enforces a pseudo probe to be virtually executed exactly the same number of times before and after an IR optimization. The intrinsic also comes with certain flags that are carefully chosen so that the places they are probing are not going to be messed up by the optimizer while most of the IR optimizations still work. The core flags given to the special intrinsic is `IntrInaccessibleMemOnly`, which means the intrinsic accesses memory and does have a side effect so that it is not removable, but is does not access memory locations that are accessible by any original instructions. This way the intrinsic does not alias with any original instruction and thus it does not block optimizations as much as an atomic operation does. We also assign a function GUID and a block index to an intrinsic so that they are uniquely identified and not merged in order to achieve good correlation quality.
Let's now look at an example. Given the following LLVM IR:
```
define internal void @foo2(i32 %x, void (i32)* %f) !dbg !4 {
bb0:
%cmp = icmp eq i32 %x, 0
br i1 %cmp, label %bb1, label %bb2
bb1:
br label %bb3
bb2:
br label %bb3
bb3:
ret void
}
```
The instrumented IR will look like below. Note that each `llvm.pseudoprobe` intrinsic call represents a pseudo probe at a block, of which the first parameter is the GUID of the probe’s owner function and the second parameter is the probe’s ID.
```
define internal void @foo2(i32 %x, void (i32)* %f) !dbg !4 {
bb0:
%cmp = icmp eq i32 %x, 0
call void @llvm.pseudoprobe(i64 837061429793323041, i64 1)
br i1 %cmp, label %bb1, label %bb2
bb1:
call void @llvm.pseudoprobe(i64 837061429793323041, i64 2)
br label %bb3
bb2:
call void @llvm.pseudoprobe(i64 837061429793323041, i64 3)
br label %bb3
bb3:
call void @llvm.pseudoprobe(i64 837061429793323041, i64 4)
ret void
}
```
Reviewed By: wmi
Differential Revision: https://reviews.llvm.org/D86490
2020-11-19 04:42:51 +08:00
|
|
|
continue;
|
2021-01-20 03:04:52 +08:00
|
|
|
// A lifetime end, assume or noalias.decl intrinsic should not stop tail
|
|
|
|
// call optimization.
|
2020-06-03 23:37:07 +08:00
|
|
|
if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(BBI))
|
|
|
|
if (II->getIntrinsicID() == Intrinsic::lifetime_end ||
|
2021-01-20 03:04:52 +08:00
|
|
|
II->getIntrinsicID() == Intrinsic::assume ||
|
|
|
|
II->getIntrinsicID() == Intrinsic::experimental_noalias_scope_decl)
|
2015-08-29 05:13:39 +08:00
|
|
|
continue;
|
2020-06-03 23:37:07 +08:00
|
|
|
if (BBI->mayHaveSideEffects() || BBI->mayReadFromMemory() ||
|
|
|
|
!isSafeToSpeculativelyExecute(&*BBI))
|
|
|
|
return false;
|
|
|
|
}
|
2010-04-21 09:22:34 +08:00
|
|
|
|
2015-02-21 02:44:17 +08:00
|
|
|
const Function *F = ExitBB->getParent();
|
2014-08-05 05:25:23 +08:00
|
|
|
return returnTypeIsEligibleForTailCall(
|
2020-04-14 14:04:52 +08:00
|
|
|
F, &Call, Ret, *TM.getSubtargetImpl(*F)->getTargetLowering());
|
2013-08-20 16:36:50 +08:00
|
|
|
}
|
|
|
|
|
2016-09-08 08:48:37 +08:00
|
|
|
bool llvm::attributesPermitTailCall(const Function *F, const Instruction *I,
|
|
|
|
const ReturnInst *Ret,
|
|
|
|
const TargetLoweringBase &TLI,
|
|
|
|
bool *AllowDifferingSizes) {
|
|
|
|
// ADS may be null, so don't write to it directly.
|
|
|
|
bool DummyADS;
|
|
|
|
bool &ADS = AllowDifferingSizes ? *AllowDifferingSizes : DummyADS;
|
|
|
|
ADS = true;
|
2010-04-21 09:22:34 +08:00
|
|
|
|
2022-01-16 05:14:16 +08:00
|
|
|
AttrBuilder CallerAttrs(F->getContext(), F->getAttributes().getRetAttrs());
|
|
|
|
AttrBuilder CalleeAttrs(F->getContext(),
|
|
|
|
cast<CallInst>(I)->getAttributes().getRetAttrs());
|
2013-08-12 17:45:46 +08:00
|
|
|
|
2019-11-07 06:07:17 +08:00
|
|
|
// Following attributes are completely benign as far as calling convention
|
2018-09-26 18:46:18 +08:00
|
|
|
// goes, they shouldn't affect whether the call is a tail call.
|
2021-04-25 01:55:04 +08:00
|
|
|
for (const auto &Attr : {Attribute::Alignment, Attribute::Dereferenceable,
|
|
|
|
Attribute::DereferenceableOrNull, Attribute::NoAlias,
|
2022-01-31 20:45:07 +08:00
|
|
|
Attribute::NonNull, Attribute::NoUndef}) {
|
2021-04-25 01:55:04 +08:00
|
|
|
CallerAttrs.removeAttribute(Attr);
|
|
|
|
CalleeAttrs.removeAttribute(Attr);
|
|
|
|
}
|
2013-08-12 17:45:46 +08:00
|
|
|
|
|
|
|
if (CallerAttrs.contains(Attribute::ZExt)) {
|
|
|
|
if (!CalleeAttrs.contains(Attribute::ZExt))
|
|
|
|
return false;
|
|
|
|
|
2016-09-08 08:48:37 +08:00
|
|
|
ADS = false;
|
2013-08-12 17:45:46 +08:00
|
|
|
CallerAttrs.removeAttribute(Attribute::ZExt);
|
|
|
|
CalleeAttrs.removeAttribute(Attribute::ZExt);
|
|
|
|
} else if (CallerAttrs.contains(Attribute::SExt)) {
|
|
|
|
if (!CalleeAttrs.contains(Attribute::SExt))
|
|
|
|
return false;
|
|
|
|
|
2016-09-08 08:48:37 +08:00
|
|
|
ADS = false;
|
2013-08-12 17:45:46 +08:00
|
|
|
CallerAttrs.removeAttribute(Attribute::SExt);
|
|
|
|
CalleeAttrs.removeAttribute(Attribute::SExt);
|
|
|
|
}
|
2010-04-21 09:22:34 +08:00
|
|
|
|
2019-01-10 03:46:15 +08:00
|
|
|
// Drop sext and zext return attributes if the result is not used.
|
|
|
|
// This enables tail calls for code like:
|
|
|
|
//
|
|
|
|
// define void @caller() {
|
|
|
|
// entry:
|
|
|
|
// %unused_result = tail call zeroext i1 @callee()
|
|
|
|
// br label %retlabel
|
|
|
|
// retlabel:
|
|
|
|
// ret void
|
|
|
|
// }
|
|
|
|
if (I->use_empty()) {
|
|
|
|
CalleeAttrs.removeAttribute(Attribute::SExt);
|
|
|
|
CalleeAttrs.removeAttribute(Attribute::ZExt);
|
|
|
|
}
|
|
|
|
|
2013-08-12 17:45:46 +08:00
|
|
|
// If they're still different, there's some facet we don't understand
|
|
|
|
// (currently only "inreg", but in future who knows). It may be OK but the
|
|
|
|
// only safe option is to reject the tail call.
|
2016-09-08 08:48:37 +08:00
|
|
|
return CallerAttrs == CalleeAttrs;
|
|
|
|
}
|
|
|
|
|
Fix missing memcpy, memmove and memset tail calls
Summary:
If a wrapper around one of the mem* stdlib functions bitcasts the returned
pointer value before returning it (e.g. to a wchar_t*), LLVM does not emit a
tail call.
Add a check for this scenario so that we emit a tail call.
Reviewers: wmi, mkuper, ramred01, dmgreen
Reviewed By: wmi, dmgreen
Subscribers: hiraditya, sanwou01, javed.absar, lebedev.ri, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59078
2019-10-31 22:55:57 +08:00
|
|
|
/// Check whether B is a bitcast of a pointer type to another pointer type,
|
|
|
|
/// which is equal to A.
|
|
|
|
static bool isPointerBitcastEqualTo(const Value *A, const Value *B) {
|
|
|
|
assert(A && B && "Expected non-null inputs!");
|
|
|
|
|
|
|
|
auto *BitCastIn = dyn_cast<BitCastInst>(B);
|
|
|
|
|
|
|
|
if (!BitCastIn)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!A->getType()->isPointerTy() || !B->getType()->isPointerTy())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return A == BitCastIn->getOperand(0);
|
|
|
|
}
|
|
|
|
|
2016-09-08 08:48:37 +08:00
|
|
|
bool llvm::returnTypeIsEligibleForTailCall(const Function *F,
|
|
|
|
const Instruction *I,
|
|
|
|
const ReturnInst *Ret,
|
|
|
|
const TargetLoweringBase &TLI) {
|
|
|
|
// If the block ends with a void return or unreachable, it doesn't matter
|
|
|
|
// what the call's return type is.
|
|
|
|
if (!Ret || Ret->getNumOperands() == 0) return true;
|
|
|
|
|
|
|
|
// If the return value is undef, it doesn't matter what the call's
|
|
|
|
// return type is.
|
|
|
|
if (isa<UndefValue>(Ret->getOperand(0))) return true;
|
|
|
|
|
|
|
|
// Make sure the attributes attached to each return are compatible.
|
|
|
|
bool AllowDifferingSizes;
|
|
|
|
if (!attributesPermitTailCall(F, I, Ret, TLI, &AllowDifferingSizes))
|
2010-04-21 09:22:34 +08:00
|
|
|
return false;
|
|
|
|
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
const Value *RetVal = Ret->getOperand(0), *CallVal = I;
|
2017-09-09 00:44:52 +08:00
|
|
|
// Intrinsic like llvm.memcpy has no return value, but the expanded
|
|
|
|
// libcall may or may not have return value. On most platforms, it
|
|
|
|
// will be expanded as memcpy in libc, which returns the first
|
|
|
|
// argument. On other platforms like arm-none-eabi, memcpy may be
|
|
|
|
// expanded as library call without return value, like __aeabi_memcpy.
|
2017-09-07 00:05:17 +08:00
|
|
|
const CallInst *Call = cast<CallInst>(I);
|
|
|
|
if (Function *F = Call->getCalledFunction()) {
|
|
|
|
Intrinsic::ID IID = F->getIntrinsicID();
|
2017-09-09 00:44:52 +08:00
|
|
|
if (((IID == Intrinsic::memcpy &&
|
|
|
|
TLI.getLibcallName(RTLIB::MEMCPY) == StringRef("memcpy")) ||
|
|
|
|
(IID == Intrinsic::memmove &&
|
|
|
|
TLI.getLibcallName(RTLIB::MEMMOVE) == StringRef("memmove")) ||
|
|
|
|
(IID == Intrinsic::memset &&
|
|
|
|
TLI.getLibcallName(RTLIB::MEMSET) == StringRef("memset"))) &&
|
Fix missing memcpy, memmove and memset tail calls
Summary:
If a wrapper around one of the mem* stdlib functions bitcasts the returned
pointer value before returning it (e.g. to a wchar_t*), LLVM does not emit a
tail call.
Add a check for this scenario so that we emit a tail call.
Reviewers: wmi, mkuper, ramred01, dmgreen
Reviewed By: wmi, dmgreen
Subscribers: hiraditya, sanwou01, javed.absar, lebedev.ri, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59078
2019-10-31 22:55:57 +08:00
|
|
|
(RetVal == Call->getArgOperand(0) ||
|
|
|
|
isPointerBitcastEqualTo(RetVal, Call->getArgOperand(0))))
|
2017-09-07 00:05:17 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
SmallVector<unsigned, 4> RetPath, CallPath;
|
2020-03-04 07:42:16 +08:00
|
|
|
SmallVector<Type *, 4> RetSubTypes, CallSubTypes;
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
|
|
|
|
bool RetEmpty = !firstRealType(RetVal->getType(), RetSubTypes, RetPath);
|
|
|
|
bool CallEmpty = !firstRealType(CallVal->getType(), CallSubTypes, CallPath);
|
|
|
|
|
|
|
|
// Nothing's actually returned, it doesn't matter what the callee put there
|
|
|
|
// it's a valid tail call.
|
|
|
|
if (RetEmpty)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Iterate pairwise through each of the value types making up the tail call
|
|
|
|
// and the corresponding return. For each one we want to know whether it's
|
|
|
|
// essentially going directly from the tail call to the ret, via operations
|
|
|
|
// that end up not generating any code.
|
|
|
|
//
|
|
|
|
// We allow a certain amount of covariance here. For example it's permitted
|
|
|
|
// for the tail call to define more bits than the ret actually cares about
|
|
|
|
// (e.g. via a truncate).
|
|
|
|
do {
|
|
|
|
if (CallEmpty) {
|
|
|
|
// We've exhausted the values produced by the tail call instruction, the
|
|
|
|
// rest are essentially undef. The type doesn't really matter, but we need
|
|
|
|
// *something*.
|
2020-03-04 07:42:16 +08:00
|
|
|
Type *SlotType =
|
|
|
|
ExtractValueInst::getIndexedType(RetSubTypes.back(), RetPath.back());
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
CallVal = UndefValue::get(SlotType);
|
|
|
|
}
|
|
|
|
|
|
|
|
// The manipulations performed when we're looking through an insertvalue or
|
|
|
|
// an extractvalue would happen at the front of the RetPath list, so since
|
|
|
|
// we have to copy it anyway it's more efficient to create a reversed copy.
|
2021-12-21 15:43:23 +08:00
|
|
|
SmallVector<unsigned, 4> TmpRetPath(llvm::reverse(RetPath));
|
|
|
|
SmallVector<unsigned, 4> TmpCallPath(llvm::reverse(CallPath));
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
|
|
|
|
// Finally, we can check whether the value produced by the tail call at this
|
|
|
|
// index is compatible with the value we return.
|
2013-08-12 17:45:46 +08:00
|
|
|
if (!slotOnlyDiscardsData(RetVal, CallVal, TmpRetPath, TmpCallPath,
|
2015-07-09 10:09:04 +08:00
|
|
|
AllowDifferingSizes, TLI,
|
|
|
|
F->getParent()->getDataLayout()))
|
Refactor isInTailCallPosition handling
This change came about primarily because of two issues in the existing code.
Niether of:
define i64 @test1(i64 %val) {
%in = trunc i64 %val to i32
tail call i32 @ret32(i32 returned %in)
ret i64 %val
}
define i64 @test2(i64 %val) {
tail call i32 @ret32(i32 returned undef)
ret i32 42
}
should be tail calls, and the function sameNoopInput is responsible. The main
problem is that it is completely symmetric in the "tail call" and "ret" value,
but in reality different things are allowed on each side.
For these cases:
1. Any truncation should lead to a larger value being generated by "tail call"
than needed by "ret".
2. Undef should only be allowed as a source for ret, not as a result of the
call.
Along the way I noticed that a mismatch between what this function treats as a
valid truncation and what the backends see can lead to invalid calls as well
(see x86-32 test case).
This patch refactors the code so that instead of being based primarily on
values which it recurses into when necessary, it starts by inspecting the type
and considers each fundamental slot that the backend will see in turn. For
example, given a pathological function that returned {{}, {{}, i32, {}}, i32}
we would consider each "real" i32 in turn, and ask if it passes through
unchanged. This is much closer to what the backend sees as a result of
ComputeValueVTs.
Aside from the bug fixes, this eliminates the recursion that's going on and, I
believe, makes the bulk of the code significantly easier to understand. The
trade-off is the nasty iterators needed to find the real types inside a
returned value.
llvm-svn: 187787
2013-08-06 17:12:35 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
CallEmpty = !nextRealType(CallSubTypes, CallPath);
|
|
|
|
} while(nextRealType(RetSubTypes, RetPath));
|
|
|
|
|
|
|
|
return true;
|
2010-04-21 09:22:34 +08:00
|
|
|
}
|
2014-07-31 03:42:16 +08:00
|
|
|
|
2018-06-01 08:03:21 +08:00
|
|
|
static void collectEHScopeMembers(
|
|
|
|
DenseMap<const MachineBasicBlock *, int> &EHScopeMembership, int EHScope,
|
|
|
|
const MachineBasicBlock *MBB) {
|
2016-01-23 02:49:50 +08:00
|
|
|
SmallVector<const MachineBasicBlock *, 16> Worklist = {MBB};
|
|
|
|
while (!Worklist.empty()) {
|
|
|
|
const MachineBasicBlock *Visiting = Worklist.pop_back_val();
|
[WebAssembly] Add functions for EHScopes
Summary:
There are functions using the term 'funclet' to refer to both
1. an EH scopes, the structure of BBs that starts with
catchpad/cleanuppad and ends with catchret/cleanupret, and
2. a small function that gets outlined in AsmPrinter, which is the
original meaning of 'funclet'.
So far the two have been the same thing; EH scopes are always outlined
in AsmPrinter as funclets at the end of the compilation pipeline. But
now wasm also uses scope-based EH but does not outline those, so we now
need to correctly distinguish those two use cases in functions.
This patch splits `MachineBasicBlock::isFuncletEntry` into
`isFuncletEntry` and `isEHScopeEntry`, and
`MachineFunction::hasFunclets` into `hasFunclets` and `hasEHScopes`, in
order to distinguish the two different use cases. And this also changes
some uses of the term 'funclet' to 'scope' in `getFuncletMembership` and
change the function name to `getEHScopeMembership` because this function
is not about outlined funclets but about EH scope memberships.
This change is in the same vein as D45559.
Reviewers: majnemer, dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D47005
llvm-svn: 333045
2018-05-23 08:32:46 +08:00
|
|
|
// Don't follow blocks which start new scopes.
|
2016-01-23 02:49:50 +08:00
|
|
|
if (Visiting->isEHPad() && Visiting != MBB)
|
|
|
|
continue;
|
|
|
|
|
[WebAssembly] Add functions for EHScopes
Summary:
There are functions using the term 'funclet' to refer to both
1. an EH scopes, the structure of BBs that starts with
catchpad/cleanuppad and ends with catchret/cleanupret, and
2. a small function that gets outlined in AsmPrinter, which is the
original meaning of 'funclet'.
So far the two have been the same thing; EH scopes are always outlined
in AsmPrinter as funclets at the end of the compilation pipeline. But
now wasm also uses scope-based EH but does not outline those, so we now
need to correctly distinguish those two use cases in functions.
This patch splits `MachineBasicBlock::isFuncletEntry` into
`isFuncletEntry` and `isEHScopeEntry`, and
`MachineFunction::hasFunclets` into `hasFunclets` and `hasEHScopes`, in
order to distinguish the two different use cases. And this also changes
some uses of the term 'funclet' to 'scope' in `getFuncletMembership` and
change the function name to `getEHScopeMembership` because this function
is not about outlined funclets but about EH scope memberships.
This change is in the same vein as D45559.
Reviewers: majnemer, dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D47005
llvm-svn: 333045
2018-05-23 08:32:46 +08:00
|
|
|
// Add this MBB to our scope.
|
2018-06-01 08:03:21 +08:00
|
|
|
auto P = EHScopeMembership.insert(std::make_pair(Visiting, EHScope));
|
2016-01-23 02:49:50 +08:00
|
|
|
|
|
|
|
// Don't revisit blocks.
|
|
|
|
if (!P.second) {
|
2018-06-01 08:03:21 +08:00
|
|
|
assert(P.first->second == EHScope && "MBB is part of two scopes!");
|
2016-01-23 02:49:50 +08:00
|
|
|
continue;
|
|
|
|
}
|
2015-10-27 02:41:13 +08:00
|
|
|
|
[WebAssembly] Add functions for EHScopes
Summary:
There are functions using the term 'funclet' to refer to both
1. an EH scopes, the structure of BBs that starts with
catchpad/cleanuppad and ends with catchret/cleanupret, and
2. a small function that gets outlined in AsmPrinter, which is the
original meaning of 'funclet'.
So far the two have been the same thing; EH scopes are always outlined
in AsmPrinter as funclets at the end of the compilation pipeline. But
now wasm also uses scope-based EH but does not outline those, so we now
need to correctly distinguish those two use cases in functions.
This patch splits `MachineBasicBlock::isFuncletEntry` into
`isFuncletEntry` and `isEHScopeEntry`, and
`MachineFunction::hasFunclets` into `hasFunclets` and `hasEHScopes`, in
order to distinguish the two different use cases. And this also changes
some uses of the term 'funclet' to 'scope' in `getFuncletMembership` and
change the function name to `getEHScopeMembership` because this function
is not about outlined funclets but about EH scope memberships.
This change is in the same vein as D45559.
Reviewers: majnemer, dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D47005
llvm-svn: 333045
2018-05-23 08:32:46 +08:00
|
|
|
// Returns are boundaries where scope transfer can occur, don't follow
|
2016-01-23 02:49:50 +08:00
|
|
|
// successors.
|
2018-08-22 03:44:11 +08:00
|
|
|
if (Visiting->isEHScopeReturnBlock())
|
2016-01-23 02:49:50 +08:00
|
|
|
continue;
|
2015-10-04 10:22:52 +08:00
|
|
|
|
2021-01-22 11:59:46 +08:00
|
|
|
append_range(Worklist, Visiting->successors());
|
2015-10-04 10:22:52 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DenseMap<const MachineBasicBlock *, int>
|
[WebAssembly] Add functions for EHScopes
Summary:
There are functions using the term 'funclet' to refer to both
1. an EH scopes, the structure of BBs that starts with
catchpad/cleanuppad and ends with catchret/cleanupret, and
2. a small function that gets outlined in AsmPrinter, which is the
original meaning of 'funclet'.
So far the two have been the same thing; EH scopes are always outlined
in AsmPrinter as funclets at the end of the compilation pipeline. But
now wasm also uses scope-based EH but does not outline those, so we now
need to correctly distinguish those two use cases in functions.
This patch splits `MachineBasicBlock::isFuncletEntry` into
`isFuncletEntry` and `isEHScopeEntry`, and
`MachineFunction::hasFunclets` into `hasFunclets` and `hasEHScopes`, in
order to distinguish the two different use cases. And this also changes
some uses of the term 'funclet' to 'scope' in `getFuncletMembership` and
change the function name to `getEHScopeMembership` because this function
is not about outlined funclets but about EH scope memberships.
This change is in the same vein as D45559.
Reviewers: majnemer, dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D47005
llvm-svn: 333045
2018-05-23 08:32:46 +08:00
|
|
|
llvm::getEHScopeMembership(const MachineFunction &MF) {
|
2018-06-01 08:03:21 +08:00
|
|
|
DenseMap<const MachineBasicBlock *, int> EHScopeMembership;
|
2015-10-04 10:22:52 +08:00
|
|
|
|
|
|
|
// We don't have anything to do if there aren't any EH pads.
|
[WebAssembly] Add functions for EHScopes
Summary:
There are functions using the term 'funclet' to refer to both
1. an EH scopes, the structure of BBs that starts with
catchpad/cleanuppad and ends with catchret/cleanupret, and
2. a small function that gets outlined in AsmPrinter, which is the
original meaning of 'funclet'.
So far the two have been the same thing; EH scopes are always outlined
in AsmPrinter as funclets at the end of the compilation pipeline. But
now wasm also uses scope-based EH but does not outline those, so we now
need to correctly distinguish those two use cases in functions.
This patch splits `MachineBasicBlock::isFuncletEntry` into
`isFuncletEntry` and `isEHScopeEntry`, and
`MachineFunction::hasFunclets` into `hasFunclets` and `hasEHScopes`, in
order to distinguish the two different use cases. And this also changes
some uses of the term 'funclet' to 'scope' in `getFuncletMembership` and
change the function name to `getEHScopeMembership` because this function
is not about outlined funclets but about EH scope memberships.
This change is in the same vein as D45559.
Reviewers: majnemer, dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D47005
llvm-svn: 333045
2018-05-23 08:32:46 +08:00
|
|
|
if (!MF.hasEHScopes())
|
2018-06-01 08:03:21 +08:00
|
|
|
return EHScopeMembership;
|
2015-10-04 10:22:52 +08:00
|
|
|
|
2015-10-06 04:09:16 +08:00
|
|
|
int EntryBBNumber = MF.front().getNumber();
|
2015-10-04 10:22:52 +08:00
|
|
|
bool IsSEH = isAsynchronousEHPersonality(
|
2017-12-16 06:22:58 +08:00
|
|
|
classifyEHPersonality(MF.getFunction().getPersonalityFn()));
|
2015-10-04 10:22:52 +08:00
|
|
|
|
|
|
|
const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
|
2018-06-01 08:03:21 +08:00
|
|
|
SmallVector<const MachineBasicBlock *, 16> EHScopeBlocks;
|
2015-10-06 04:09:16 +08:00
|
|
|
SmallVector<const MachineBasicBlock *, 16> UnreachableBlocks;
|
|
|
|
SmallVector<const MachineBasicBlock *, 16> SEHCatchPads;
|
2015-10-04 10:22:52 +08:00
|
|
|
SmallVector<std::pair<const MachineBasicBlock *, int>, 16> CatchRetSuccessors;
|
|
|
|
for (const MachineBasicBlock &MBB : MF) {
|
[WebAssembly] Add functions for EHScopes
Summary:
There are functions using the term 'funclet' to refer to both
1. an EH scopes, the structure of BBs that starts with
catchpad/cleanuppad and ends with catchret/cleanupret, and
2. a small function that gets outlined in AsmPrinter, which is the
original meaning of 'funclet'.
So far the two have been the same thing; EH scopes are always outlined
in AsmPrinter as funclets at the end of the compilation pipeline. But
now wasm also uses scope-based EH but does not outline those, so we now
need to correctly distinguish those two use cases in functions.
This patch splits `MachineBasicBlock::isFuncletEntry` into
`isFuncletEntry` and `isEHScopeEntry`, and
`MachineFunction::hasFunclets` into `hasFunclets` and `hasEHScopes`, in
order to distinguish the two different use cases. And this also changes
some uses of the term 'funclet' to 'scope' in `getFuncletMembership` and
change the function name to `getEHScopeMembership` because this function
is not about outlined funclets but about EH scope memberships.
This change is in the same vein as D45559.
Reviewers: majnemer, dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D47005
llvm-svn: 333045
2018-05-23 08:32:46 +08:00
|
|
|
if (MBB.isEHScopeEntry()) {
|
2018-06-01 08:03:21 +08:00
|
|
|
EHScopeBlocks.push_back(&MBB);
|
2015-10-06 04:09:16 +08:00
|
|
|
} else if (IsSEH && MBB.isEHPad()) {
|
|
|
|
SEHCatchPads.push_back(&MBB);
|
|
|
|
} else if (MBB.pred_empty()) {
|
|
|
|
UnreachableBlocks.push_back(&MBB);
|
|
|
|
}
|
2015-10-04 10:22:52 +08:00
|
|
|
|
|
|
|
MachineBasicBlock::const_iterator MBBI = MBB.getFirstTerminator();
|
2016-08-11 23:29:02 +08:00
|
|
|
|
[WebAssembly] Add functions for EHScopes
Summary:
There are functions using the term 'funclet' to refer to both
1. an EH scopes, the structure of BBs that starts with
catchpad/cleanuppad and ends with catchret/cleanupret, and
2. a small function that gets outlined in AsmPrinter, which is the
original meaning of 'funclet'.
So far the two have been the same thing; EH scopes are always outlined
in AsmPrinter as funclets at the end of the compilation pipeline. But
now wasm also uses scope-based EH but does not outline those, so we now
need to correctly distinguish those two use cases in functions.
This patch splits `MachineBasicBlock::isFuncletEntry` into
`isFuncletEntry` and `isEHScopeEntry`, and
`MachineFunction::hasFunclets` into `hasFunclets` and `hasEHScopes`, in
order to distinguish the two different use cases. And this also changes
some uses of the term 'funclet' to 'scope' in `getFuncletMembership` and
change the function name to `getEHScopeMembership` because this function
is not about outlined funclets but about EH scope memberships.
This change is in the same vein as D45559.
Reviewers: majnemer, dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D47005
llvm-svn: 333045
2018-05-23 08:32:46 +08:00
|
|
|
// CatchPads are not scopes for SEH so do not consider CatchRet to
|
|
|
|
// transfer control to another scope.
|
2016-08-12 00:00:43 +08:00
|
|
|
if (MBBI == MBB.end() || MBBI->getOpcode() != TII->getCatchReturnOpcode())
|
2015-10-04 10:22:52 +08:00
|
|
|
continue;
|
|
|
|
|
2015-10-06 04:09:16 +08:00
|
|
|
// FIXME: SEH CatchPads are not necessarily in the parent function:
|
|
|
|
// they could be inside a finally block.
|
2015-10-04 10:22:52 +08:00
|
|
|
const MachineBasicBlock *Successor = MBBI->getOperand(0).getMBB();
|
|
|
|
const MachineBasicBlock *SuccessorColor = MBBI->getOperand(1).getMBB();
|
2015-10-06 04:09:16 +08:00
|
|
|
CatchRetSuccessors.push_back(
|
|
|
|
{Successor, IsSEH ? EntryBBNumber : SuccessorColor->getNumber()});
|
2015-10-04 10:22:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// We don't have anything to do if there aren't any EH pads.
|
2018-06-01 08:03:21 +08:00
|
|
|
if (EHScopeBlocks.empty())
|
|
|
|
return EHScopeMembership;
|
2015-10-04 10:22:52 +08:00
|
|
|
|
|
|
|
// Identify all the basic blocks reachable from the function entry.
|
2018-06-01 08:03:21 +08:00
|
|
|
collectEHScopeMembers(EHScopeMembership, EntryBBNumber, &MF.front());
|
[WebAssembly] Add functions for EHScopes
Summary:
There are functions using the term 'funclet' to refer to both
1. an EH scopes, the structure of BBs that starts with
catchpad/cleanuppad and ends with catchret/cleanupret, and
2. a small function that gets outlined in AsmPrinter, which is the
original meaning of 'funclet'.
So far the two have been the same thing; EH scopes are always outlined
in AsmPrinter as funclets at the end of the compilation pipeline. But
now wasm also uses scope-based EH but does not outline those, so we now
need to correctly distinguish those two use cases in functions.
This patch splits `MachineBasicBlock::isFuncletEntry` into
`isFuncletEntry` and `isEHScopeEntry`, and
`MachineFunction::hasFunclets` into `hasFunclets` and `hasEHScopes`, in
order to distinguish the two different use cases. And this also changes
some uses of the term 'funclet' to 'scope' in `getFuncletMembership` and
change the function name to `getEHScopeMembership` because this function
is not about outlined funclets but about EH scope memberships.
This change is in the same vein as D45559.
Reviewers: majnemer, dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D47005
llvm-svn: 333045
2018-05-23 08:32:46 +08:00
|
|
|
// All blocks not part of a scope are in the parent function.
|
2015-10-06 04:09:16 +08:00
|
|
|
for (const MachineBasicBlock *MBB : UnreachableBlocks)
|
2018-06-01 08:03:21 +08:00
|
|
|
collectEHScopeMembers(EHScopeMembership, EntryBBNumber, MBB);
|
[WebAssembly] Add functions for EHScopes
Summary:
There are functions using the term 'funclet' to refer to both
1. an EH scopes, the structure of BBs that starts with
catchpad/cleanuppad and ends with catchret/cleanupret, and
2. a small function that gets outlined in AsmPrinter, which is the
original meaning of 'funclet'.
So far the two have been the same thing; EH scopes are always outlined
in AsmPrinter as funclets at the end of the compilation pipeline. But
now wasm also uses scope-based EH but does not outline those, so we now
need to correctly distinguish those two use cases in functions.
This patch splits `MachineBasicBlock::isFuncletEntry` into
`isFuncletEntry` and `isEHScopeEntry`, and
`MachineFunction::hasFunclets` into `hasFunclets` and `hasEHScopes`, in
order to distinguish the two different use cases. And this also changes
some uses of the term 'funclet' to 'scope' in `getFuncletMembership` and
change the function name to `getEHScopeMembership` because this function
is not about outlined funclets but about EH scope memberships.
This change is in the same vein as D45559.
Reviewers: majnemer, dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D47005
llvm-svn: 333045
2018-05-23 08:32:46 +08:00
|
|
|
// Next, identify all the blocks inside the scopes.
|
2018-06-01 08:03:21 +08:00
|
|
|
for (const MachineBasicBlock *MBB : EHScopeBlocks)
|
|
|
|
collectEHScopeMembers(EHScopeMembership, MBB->getNumber(), MBB);
|
[WebAssembly] Add functions for EHScopes
Summary:
There are functions using the term 'funclet' to refer to both
1. an EH scopes, the structure of BBs that starts with
catchpad/cleanuppad and ends with catchret/cleanupret, and
2. a small function that gets outlined in AsmPrinter, which is the
original meaning of 'funclet'.
So far the two have been the same thing; EH scopes are always outlined
in AsmPrinter as funclets at the end of the compilation pipeline. But
now wasm also uses scope-based EH but does not outline those, so we now
need to correctly distinguish those two use cases in functions.
This patch splits `MachineBasicBlock::isFuncletEntry` into
`isFuncletEntry` and `isEHScopeEntry`, and
`MachineFunction::hasFunclets` into `hasFunclets` and `hasEHScopes`, in
order to distinguish the two different use cases. And this also changes
some uses of the term 'funclet' to 'scope' in `getFuncletMembership` and
change the function name to `getEHScopeMembership` because this function
is not about outlined funclets but about EH scope memberships.
This change is in the same vein as D45559.
Reviewers: majnemer, dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D47005
llvm-svn: 333045
2018-05-23 08:32:46 +08:00
|
|
|
// SEH CatchPads aren't really scopes, handle them separately.
|
2015-10-06 04:09:16 +08:00
|
|
|
for (const MachineBasicBlock *MBB : SEHCatchPads)
|
2018-06-01 08:03:21 +08:00
|
|
|
collectEHScopeMembers(EHScopeMembership, EntryBBNumber, MBB);
|
2015-10-04 10:22:52 +08:00
|
|
|
// Finally, identify all the targets of a catchret.
|
|
|
|
for (std::pair<const MachineBasicBlock *, int> CatchRetPair :
|
|
|
|
CatchRetSuccessors)
|
2018-06-01 08:03:21 +08:00
|
|
|
collectEHScopeMembers(EHScopeMembership, CatchRetPair.second,
|
2015-10-04 10:22:52 +08:00
|
|
|
CatchRetPair.first);
|
2018-06-01 08:03:21 +08:00
|
|
|
return EHScopeMembership;
|
2015-10-04 10:22:52 +08:00
|
|
|
}
|