mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
Resubmit support for the 'nocapture' attribute.
The problematic part of this patch is that we were out of attribute bits, requiring some fancy bit hacking to make it fit (by shrinking alignment) without breaking existing users or the file format. This change will require users to rebuild llvm-gcc to match llvm. llvm-svn: 61239
This commit is contained in:
parent
d4a3c71eb1
commit
8f96b51785
@ -894,9 +894,15 @@ declare signext i8 @returns_signed_char()
|
|||||||
parameter. The caller is responsible for ensuring that this is the
|
parameter. The caller is responsible for ensuring that this is the
|
||||||
case. On a function return value, <tt>noalias</tt> additionally indicates
|
case. On a function return value, <tt>noalias</tt> additionally indicates
|
||||||
that the pointer does not alias any other pointers visible to the
|
that the pointer does not alias any other pointers visible to the
|
||||||
caller. Note that this applies only to pointers that can be used to actually
|
caller. For further details, please see the discussion of the NoAlias
|
||||||
load/store a value: NULL, unique pointers from malloc(0), and freed pointers
|
response in
|
||||||
are considered to not alias anything.</dd>
|
<a href="http://llvm.org/docs/AliasAnalysis.html#MustMayNo">alias
|
||||||
|
analysis</a>.</dd>
|
||||||
|
|
||||||
|
<dt><tt>nocapture</tt></dt>
|
||||||
|
<dd>This indicates that the callee does not make any copies of the pointer
|
||||||
|
that outlive the callee itself. This is not a valid attribute for return
|
||||||
|
values.</dd>
|
||||||
|
|
||||||
<dt><tt>nest</tt></dt>
|
<dt><tt>nest</tt></dt>
|
||||||
<dd>This indicates that the pointer parameter can be excised using the
|
<dd>This indicates that the pointer parameter can be excised using the
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#ifndef LLVM_ATTRIBUTES_H
|
#ifndef LLVM_ATTRIBUTES_H
|
||||||
#define LLVM_ATTRIBUTES_H
|
#define LLVM_ATTRIBUTES_H
|
||||||
|
|
||||||
|
#include "llvm/Support/MathExtras.h"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -23,7 +24,7 @@ class Type;
|
|||||||
|
|
||||||
/// Attributes - A bitset of attributes.
|
/// Attributes - A bitset of attributes.
|
||||||
typedef unsigned Attributes;
|
typedef unsigned Attributes;
|
||||||
|
|
||||||
namespace Attribute {
|
namespace Attribute {
|
||||||
|
|
||||||
/// Function parameters and results can have attributes to indicate how they
|
/// Function parameters and results can have attributes to indicate how they
|
||||||
@ -44,16 +45,18 @@ const Attributes ByVal = 1<<7; ///< Pass structure by value
|
|||||||
const Attributes Nest = 1<<8; ///< Nested function static chain
|
const Attributes Nest = 1<<8; ///< Nested function static chain
|
||||||
const Attributes ReadNone = 1<<9; ///< Function does not access memory
|
const Attributes ReadNone = 1<<9; ///< Function does not access memory
|
||||||
const Attributes ReadOnly = 1<<10; ///< Function only reads from memory
|
const Attributes ReadOnly = 1<<10; ///< Function only reads from memory
|
||||||
const Attributes NoInline = 1<<11; // inline=never
|
const Attributes NoInline = 1<<11; ///< inline=never
|
||||||
const Attributes AlwaysInline = 1<<12; // inline=always
|
const Attributes AlwaysInline = 1<<12; ///< inline=always
|
||||||
const Attributes OptimizeForSize = 1<<13; // opt_size
|
const Attributes OptimizeForSize = 1<<13; ///< opt_size
|
||||||
const Attributes StackProtect = 1<<14; // Stack protection.
|
const Attributes StackProtect = 1<<14; ///< Stack protection.
|
||||||
const Attributes StackProtectReq = 1<<15; // Stack protection required.
|
const Attributes StackProtectReq = 1<<15; ///< Stack protection required.
|
||||||
const Attributes Alignment = 0xffff<<16; ///< Alignment of parameter (16 bits)
|
const Attributes Alignment = 31<<16; ///< Alignment of parameter (5 bits)
|
||||||
// 0 = unknown, else in clear (not log)
|
// stored as log2 of alignment with +1 bias
|
||||||
|
// 0 means unaligned different from align 1
|
||||||
|
const Attributes NoCapture = 1<<21; ///< Function creates no aliases of pointer
|
||||||
|
|
||||||
/// @brief Attributes that only apply to function parameters.
|
/// @brief Attributes that only apply to function parameters.
|
||||||
const Attributes ParameterOnly = ByVal | Nest | StructRet;
|
const Attributes ParameterOnly = ByVal | Nest | StructRet | NoCapture;
|
||||||
|
|
||||||
/// @brief Attributes that only apply to function.
|
/// @brief Attributes that only apply to function.
|
||||||
const Attributes FunctionOnly = NoReturn | NoUnwind | ReadNone | ReadOnly |
|
const Attributes FunctionOnly = NoReturn | NoUnwind | ReadNone | ReadOnly |
|
||||||
@ -64,7 +67,7 @@ const Attributes VarArgsIncompatible = StructRet;
|
|||||||
|
|
||||||
/// @brief Attributes that are mutually incompatible.
|
/// @brief Attributes that are mutually incompatible.
|
||||||
const Attributes MutuallyIncompatible[4] = {
|
const Attributes MutuallyIncompatible[4] = {
|
||||||
ByVal | InReg | Nest | StructRet,
|
ByVal | InReg | Nest | StructRet,
|
||||||
ZExt | SExt,
|
ZExt | SExt,
|
||||||
ReadNone | ReadOnly,
|
ReadNone | ReadOnly,
|
||||||
NoInline | AlwaysInline
|
NoInline | AlwaysInline
|
||||||
@ -76,7 +79,13 @@ Attributes typeIncompatible(const Type *Ty);
|
|||||||
/// This turns an int alignment (a power of 2, normally) into the
|
/// This turns an int alignment (a power of 2, normally) into the
|
||||||
/// form used internally in Attributes.
|
/// form used internally in Attributes.
|
||||||
inline Attributes constructAlignmentFromInt(unsigned i) {
|
inline Attributes constructAlignmentFromInt(unsigned i) {
|
||||||
return (i << 16);
|
// Default alignment, allow the target to define how to align it.
|
||||||
|
if (i == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
assert(isPowerOf2_32(i) && "Alignment must be a power of two.");
|
||||||
|
assert(i <= 0x40000000 && "Alignment too large.");
|
||||||
|
return (Log2_32(i)+1) << 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The set of Attributes set in Attributes is converted to a
|
/// The set of Attributes set in Attributes is converted to a
|
||||||
@ -175,7 +184,11 @@ public:
|
|||||||
/// getParamAlignment - Return the alignment for the specified function
|
/// getParamAlignment - Return the alignment for the specified function
|
||||||
/// parameter.
|
/// parameter.
|
||||||
unsigned getParamAlignment(unsigned Idx) const {
|
unsigned getParamAlignment(unsigned Idx) const {
|
||||||
return (getAttributes(Idx) & Attribute::Alignment) >> 16;
|
Attributes Align = getAttributes(Idx) & Attribute::Alignment;
|
||||||
|
if (Align == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1ull << ((Align >> 16) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// hasAttrSomewhere - Return true if the specified attribute is set for at
|
/// hasAttrSomewhere - Return true if the specified attribute is set for at
|
||||||
|
@ -63,12 +63,23 @@ static bool AddressMightEscape(const Value *V) {
|
|||||||
// callees could modify it.
|
// callees could modify it.
|
||||||
break; // next use
|
break; // next use
|
||||||
case Instruction::Call:
|
case Instruction::Call:
|
||||||
// If the call is to a few known safe intrinsics, we know that it does
|
// If the argument to the call has the nocapture attribute, then the call
|
||||||
// not escape.
|
// may store or load to the pointer, but it cannot escape.
|
||||||
// TODO: Eventually just check the 'nocapture' attribute.
|
if (cast<CallInst>(I)->paramHasAttr(UI.getOperandNo(),
|
||||||
if (!isa<MemIntrinsic>(I))
|
Attribute::NoCapture))
|
||||||
return true;
|
continue;
|
||||||
break; // next use
|
|
||||||
|
// FIXME: MemIntrinsics should have their operands marked nocapture!
|
||||||
|
if (isa<MemIntrinsic>(I))
|
||||||
|
continue; // next use
|
||||||
|
return true;
|
||||||
|
case Instruction::Invoke:
|
||||||
|
// If the argument to the call has the nocapture attribute, then the call
|
||||||
|
// may store or load to the pointer, but it cannot escape.
|
||||||
|
if (cast<InvokeInst>(I)->paramHasAttr(UI.getOperandNo()-2,
|
||||||
|
Attribute::NoCapture))
|
||||||
|
continue;
|
||||||
|
return true;
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
14
test/Analysis/BasicAA/nocapture.ll
Normal file
14
test/Analysis/BasicAA/nocapture.ll
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
; RUN: llvm-as < %s | opt -basicaa -gvn -instcombine | llvm-dis | grep {ret i32 0}
|
||||||
|
|
||||||
|
declare i32* @test(i32* nocapture)
|
||||||
|
|
||||||
|
define i32 @test2() {
|
||||||
|
%P = alloca i32
|
||||||
|
%Q = call i32* @test(i32* %P)
|
||||||
|
%a = load i32* %P
|
||||||
|
store i32 4, i32* %Q ;; cannot clobber P since it is nocapture.
|
||||||
|
%b = load i32* %P
|
||||||
|
%c = sub i32 %a, %b
|
||||||
|
ret i32 %c
|
||||||
|
}
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user