Any thoughts on this?
On Fri, Apr 19, 2013 at 11:51 AM, Reid Kleckner <[email protected]> wrote: > Hi rjmccall, > > Like Itanium, comparisons are basically bitwise comparisons of the two > values, with an exception for null member function pointers. If two > function pointers are null, only the function pointer field matters for > comparison purposes. The rest of the bits can be arbitrary. We take > advantage of this in isZeroInitializable(), and it may matter once we > start emitting conversions. > > http://llvm-reviews.chandlerc.com/D695 > > Files: > lib/CodeGen/MicrosoftCXXABI.cpp > test/CodeGenCXX/microsoft-abi-member-pointers.cpp > > Index: lib/CodeGen/MicrosoftCXXABI.cpp > =================================================================== > --- lib/CodeGen/MicrosoftCXXABI.cpp > +++ lib/CodeGen/MicrosoftCXXABI.cpp > @@ -149,6 +149,12 @@ > virtual llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT, > CharUnits offset); > > + virtual llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF, > + llvm::Value *L, > + llvm::Value *R, > + const MemberPointerType > *MPT, > + bool Inequality); > + > virtual llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF, > llvm::Value *MemPtr, > const MemberPointerType > *MPT); > @@ -415,6 +421,10 @@ > return Inheritance == MSIM_Unspecified; > } > > +static bool hasOnlyOneField(MSInheritanceModel Inheritance) { > + return Inheritance <= MSIM_SinglePolymorphic; > +} > + > // Only member pointers to functions need a this adjustment, since it can be > // combined with the field offset for data pointers. > static bool hasNonVirtualBaseAdjustmentField(const MemberPointerType *MPT, > @@ -531,6 +541,66 @@ > return llvm::ConstantStruct::getAnon(fields); > } > > +/// Member pointers are the same if they're either bitwise identical *or* > both > +/// null. Null-ness for function members is determined by the first field, > +/// while for data member pointers we must compare all fields. > +llvm::Value * > +MicrosoftCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF, > + llvm::Value *L, > + llvm::Value *R, > + const MemberPointerType *MPT, > + bool Inequality) { > + CGBuilderTy &Builder = CGF.Builder; > + llvm::ICmpInst::Predicate Eq; > + llvm::Instruction::BinaryOps And, Or; > + if (Inequality) { > + Eq = llvm::ICmpInst::ICMP_NE; > + And = llvm::Instruction::Or; > + Or = llvm::Instruction::And; > + } else { > + Eq = llvm::ICmpInst::ICMP_EQ; > + And = llvm::Instruction::And; > + Or = llvm::Instruction::Or; > + } > + > + // If this is a single field member pointer (single inheritance), this is a > + // single icmp. > + const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl(); > + MSInheritanceModel Inheritance = RD->getMSInheritanceModel(); > + if (hasOnlyOneField(Inheritance)) > + return Builder.CreateICmp(Eq, L, R); > + > + // Compare the first field. > + llvm::Value *L0 = Builder.CreateExtractValue(L, 0, "lhs.0"); > + llvm::Value *R0 = Builder.CreateExtractValue(R, 0, "rhs.0"); > + llvm::Value *Cmp0 = Builder.CreateICmp(Eq, L0, R0); > + > + // Compare everything other than the first field. > + llvm::Value *Res = 0; > + for (unsigned I = 1, E = > cast<llvm::StructType>(L->getType())->getNumElements(); > + I != E; ++I) { > + llvm::Value *LField = Builder.CreateExtractValue(L, I); > + llvm::Value *RField = Builder.CreateExtractValue(R, I); > + llvm::Value *Cmp = Builder.CreateICmp(Eq, LField, RField); > + if (Res) > + Res = Builder.CreateBinOp(And, Res, Cmp, "memptr.tobool"); > + else > + Res = Cmp; > + } > + > + // Check if the first field is 0 if this is a function pointer. > + if (MPT->isMemberFunctionPointer()) { > + // (l1 == r1 && ...) || l0 == 0 > + llvm::Value *Zero = llvm::Constant::getNullValue(L0->getType()); > + llvm::Value *IsZero = Builder.CreateICmp(Eq, L0, Zero); > + Res = Builder.CreateBinOp(Or, Res, IsZero, "memptr.tobool"); > + } > + > + // Combine the comparison of the first field, which must always be true for > + // this comparison to succeeed. > + return Builder.CreateBinOp(And, Res, Cmp0, "memptr.tobool"); > +} > + > llvm::Value * > MicrosoftCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF, > llvm::Value *MemPtr, > Index: test/CodeGenCXX/microsoft-abi-member-pointers.cpp > =================================================================== > --- test/CodeGenCXX/microsoft-abi-member-pointers.cpp > +++ test/CodeGenCXX/microsoft-abi-member-pointers.cpp > @@ -222,3 +222,91 @@ > // CHECK: ret void > // CHECK: } > } > + > +bool compareSingleFunctionMemptr(void (Single::*l)(), void (Single::*r)()) { > + return l == r; > +// Should only be one comparison here. > +// CHECK: define zeroext i1 > @"\01?compareSingleFunctionMemptr@@YA_NP8Single@@AEXXZ0@Z"{{.*}} { > +// CHECK-NOT: icmp > +// CHECK: %[[r:.*]] = icmp eq > +// CHECK-NOT: icmp > +// CHECK: ret i1 %[[r]] > +// CHECK: } > +} > + > +bool compareNeqSingleFunctionMemptr(void (Single::*l)(), void > (Single::*r)()) { > + return l != r; > +// Should only be one comparison here. > +// CHECK: define zeroext i1 > @"\01?compareNeqSingleFunctionMemptr@@YA_NP8Single@@AEXXZ0@Z"{{.*}} { > +// CHECK-NOT: icmp > +// CHECK: %[[r:.*]] = icmp ne > +// CHECK-NOT: icmp > +// CHECK: ret i1 %[[r]] > +// CHECK: } > +} > + > +bool unspecFuncMemptrEq(void (Unspecified::*l)(), void (Unspecified::*r)()) { > + return l == r; > +// CHECK: define zeroext i1 > @"\01?unspecFuncMemptrEq@@YA_NP8Unspecified@@AEXXZ0@Z"{{.*}} { > +// CHECK: %[[lhs0:.*]] = extractvalue { i8*, i32, i32, i32 } %[[l:.*]], 0 > +// CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r:.*]], 0 > +// CHECK: %[[cmp0:.*]] = icmp eq i8* %[[lhs0]], %{{.*}} > +// CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[l]], 1 > +// CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r]], 1 > +// CHECK: %[[cmp1:.*]] = icmp eq i32 > +// CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[l]], 2 > +// CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r]], 2 > +// CHECK: %[[cmp2:.*]] = icmp eq i32 > +// CHECK: %[[res12:.*]] = and i1 %[[cmp1]], %[[cmp2]] > +// CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[l]], 3 > +// CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r]], 3 > +// CHECK: %[[cmp3:.*]] = icmp eq i32 > +// CHECK: %[[res123:.*]] = and i1 %[[res12]], %[[cmp3]] > +// CHECK: %[[iszero:.*]] = icmp eq i8* %[[lhs0]], null > +// CHECK: %[[bits_or_null:.*]] = or i1 %[[res123]], %[[iszero]] > +// CHECK: %{{.*}} = and i1 %[[bits_or_null]], %[[cmp0]] > +// CHECK: ret i1 %{{.*}} > +// CHECK: } > +} > + > +bool unspecFuncMemptrNeq(void (Unspecified::*l)(), void (Unspecified::*r)()) > { > + return l != r; > +// CHECK: define zeroext i1 > @"\01?unspecFuncMemptrNeq@@YA_NP8Unspecified@@AEXXZ0@Z"{{.*}} { > +// CHECK: %[[lhs0:.*]] = extractvalue { i8*, i32, i32, i32 } %[[l:.*]], 0 > +// CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r:.*]], 0 > +// CHECK: %[[cmp0:.*]] = icmp ne i8* %[[lhs0]], %{{.*}} > +// CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[l]], 1 > +// CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r]], 1 > +// CHECK: %[[cmp1:.*]] = icmp ne i32 > +// CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[l]], 2 > +// CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r]], 2 > +// CHECK: %[[cmp2:.*]] = icmp ne i32 > +// CHECK: %[[res12:.*]] = or i1 %[[cmp1]], %[[cmp2]] > +// CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[l]], 3 > +// CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r]], 3 > +// CHECK: %[[cmp3:.*]] = icmp ne i32 > +// CHECK: %[[res123:.*]] = or i1 %[[res12]], %[[cmp3]] > +// CHECK: %[[iszero:.*]] = icmp ne i8* %[[lhs0]], null > +// CHECK: %[[bits_or_null:.*]] = and i1 %[[res123]], %[[iszero]] > +// CHECK: %{{.*}} = or i1 %[[bits_or_null]], %[[cmp0]] > +// CHECK: ret i1 %{{.*}} > +// CHECK: } > +} > + > +bool unspecDataMemptrEq(int Unspecified::*l, int Unspecified::*r) { > + return l == r; > +// CHECK: define zeroext i1 > @"\01?unspecDataMemptrEq@@YA_NPQUnspecified@@H0@Z"{{.*}} { > +// CHECK: extractvalue { i32, i32, i32 } %{{.*}}, 0 > +// CHECK: extractvalue { i32, i32, i32 } %{{.*}}, 0 > +// CHECK: icmp eq i32 > +// CHECK: extractvalue { i32, i32, i32 } %{{.*}}, 1 > +// CHECK: extractvalue { i32, i32, i32 } %{{.*}}, 1 > +// CHECK: icmp eq i32 > +// CHECK: extractvalue { i32, i32, i32 } %{{.*}}, 2 > +// CHECK: extractvalue { i32, i32, i32 } %{{.*}}, 2 > +// CHECK: icmp eq i32 > +// CHECK: and i1 > +// CHECK: and i1 > +// CHECK: ret i1 > +// CHECK: } > +} _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
