[cfe-dev] [RFC] Setting dereferenceable flag on the implicit this parameter for non-static member functions

Martin J. O'Riordan via cfe-dev cfe-dev at lists.llvm.org
Wed Dec 6 11:32:15 PST 2017


I think that the key concept goes all the way back to the original C++ Standard (C++98), where section 5.2.2 “Function Call” states:

 

The first expression in the postfix expression is then called the object expression, and the call

is as a member of the object pointed to or referred to. In the case of an implicit class member access, the

implied object is the one pointed to by this. [Note: a member function call of the form f() is interpreted

as (*this).f() (see 9.3.1). ]

 

A NULL pointer does not point to an object, so two things make a NULL ‘this’ invalid - first the object expression does not refer to an object and is thus undefined; and second, the note which clarifies that it is equivalent to ‘(*this).’ means that if ‘this’ is NULL, then it is a NULL pointer dereference which is already undefined behaviour elsewhere in the Standard.  I can’t remember if “notes” are normative.

 

In “very old C++”, i.e. prior to the introduction of static member functions (circa 1987), the following idiom was not unusual to get the semantic intent of a static member provide that ‘this’ was neither implicitly nor explicitly used:

 

class T {

public:

  void wishIwasStatic();

};

 

...

((T*)0)->wishIwasStatic();

 

Such functions had access to all object of type ‘T’, but without the need for ‘friend’ declarations.  But this was only a stop-gap until the introduction of static member functions was devised.

 

I very much doubt that pre-C++98 code such as this is still part of any production application, and if it is, it really ought to be rewritten.

 

Making ‘this’ not de-referenceable seems to me to be a really good idea semantically, and if it yields performance advantages too, then this is a really good thing.  Perhaps it might be a good idea to ping either Bjarne Stroustrup or the C++ Standards committee to be sure - though I expect many of the committee’s members are also participants in this forum.

 

            MartinO

 

From: cfe-dev [mailto:cfe-dev-bounces at lists.llvm.org] On Behalf Of Hal Finkel via cfe-dev
Sent: 06 December 2017 13:07
To: Lei Huang <lei at ca.ibm.com>; cfe-dev at lists.llvm.org
Cc: LLVM on Power <powerllvm at ca.ibm.com>
Subject: Re: [cfe-dev] [RFC] Setting dereferenceable flag on the implicit this parameter for non-static member functions

 

 

On 12/05/2017 01:47 PM, Lei Huang via cfe-dev wrote:

 

Hello,
 
In the discussion on bugzilla 30729, it is mentioned that the 'this' pointer needs to be valid upon entry to a non-static method.  Does the standard guarantee this is non-null on entry?


Yes. You have to call a non-static member function on a valid object.




 If so, is there a reason we can't use that fact to mark 'this' as 'dereferenceable(sizeof(*this))'?


Yes, this seems like a good idea.

 -Hal




 
There are LICM optimizations we can do based on the knowledge that 'this' is non-null on entry to a non-static member function. 
 
eg.  For the following IR,  the two highlighted loads are not being hoisted out of the for loop because we are not able to guarantee that the pointer is non-null.  If the 'this' pointer is guaranteed to be non-null on entry and we mark it thus,  then the 2 loads within the for-loop body can then be hoisted out into the loop preheader.
 
This is of course just one example of an optimization we could perform based on this knowledge, but there are probably a number of others (i.e. anything that relies on a pointer being 'dereferenceable(N)').
 
$ cat a.ll
target datalayout = "e-m:e-i64:64-n32:64"
target triple = "powerpc64le-unknown-linux-gnu"
%struct.S = type { <4 x i32>, <4 x i32> }
; Function Attrs: norecurse nounwind readonly
define <4 x i32> @_ZNK1S20constShouldBeHoistedEmDv4_i(%struct.S* nocapture readonly %this, i64 %n, <4 x
i32> %x) align 2 {
entry:
 %tobool9 = icmp eq i64 %n, 0
 br i1 %tobool9, label %for.end, label %for.body.lr.ph
for.body.lr.ph:                                   ; preds = %entry
 %k1 = getelementptr inbounds %struct.S, %struct.S* %this, i64 0, i32 0
 %k2 = getelementptr inbounds %struct.S, %struct.S* %this, i64 0, i32 1
 br label %for.body
for.body:                                         ; preds = %for.body.lr.ph, %if.end
 %n.addr.011 = phi i64 [ %n, %for.body.lr.ph ], [ %div, %if.end ]
 %x.addr.010 = phi <4 x i32> [ %x, %for.body.lr.ph ], [ %x.addr.1, %if.end ]
 %rem = and i64 %n.addr.011, 15
 %cmp = icmp eq i64 %rem, 0
 br i1 %cmp, label %if.end, label %if.then
if.then:                                          ; preds = %for.body
 %0 = load <4 x i32>, <4 x i32>* %k1, align 16
 %add = add <4 x i32> %0, %x.addr.010
 %1 = load <4 x i32>, <4 x i32>* %k2, align 16
 %xor = xor <4 x i32> %add, %1
 br label %if.end
if.end:                                           ; preds = %for.body, %if.then
 %x.addr.1 = phi <4 x i32> [ %xor, %if.then ], [ %x.addr.010, %for.body ]
 %div = lshr i64 %n.addr.011, 4
 %tobool = icmp eq i64 %div, 0
 br i1 %tobool, label %for.end, label %for.body
for.end:                                          ; preds = %if.end, %entry
 %x.addr.0.lcssa = phi <4 x i32> [ %x, %entry ], [ %x.addr.1, %if.end ]
 ret <4 x i32> %x.addr.0.lcssa
}
 

 


Regards,
Lei Huang

 

 

LLVM Development on POWER

Internal mail: C2/YGK/8200/MKM
Phone: (905) 413-4419
TieLine: 969-4419
E-mail: lei at ca.ibm.com <mailto:lei at ca.ibm.com> 







_______________________________________________
cfe-dev mailing list
cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org> 
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev





-- 
Hal Finkel
Lead, Compiler Technology and Programming Languages
Leadership Computing Facility
Argonne National Laboratory
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20171206/695126ae/attachment-0001.html>


More information about the cfe-dev mailing list