It looks like the tests you've added here rely on having an asserts build. Specifically:
> +// CHECK: [[sto:%[0-9]+]] = load i[[bits]]* %addr the function this matches looks like so with asserts: define void @set_stack_pointer_addr(i64 %addr) #0 { entry: %addr.addr = alloca i64, align 8 store i64 %addr, i64* %addr.addr, align 8 %0 = load i64* %addr.addr, align 8 call void @llvm.write_register.i64(metadata !0, i64 %0) ret void } So we match here: %0 = load i64* %addr.addr, align 8 but in release, the line reads like so instead: %2 = load i64* %1, align 8 so the %addr doesn't match. Would you mind taking a look? Renato Golin <renato.go...@linaro.org> writes: > Author: rengolin > Date: Mon May 19 13:15:42 2014 > New Revision: 209149 > > URL: http://llvm.org/viewvc/llvm-project?rev=209149&view=revLog: > Non-allocatable Global Named Register > > This patch implements global named registers in Clang, lowering to the just > created intrinsics in LLVM (@llvm.read/write_register). A new type of LValue > had to be created (Register), which just adds support to carry the metadata > node containing the name of the register. Two new methods to emit loads and > stores interoperate with another to emit the named metadata node. > > No guarantees are being made and only non-allocatable global variable named > registers are being supported. Local named register support is unchanged. > > Added: > cfe/trunk/test/CodeGen/named_reg_global.c > Modified: > cfe/trunk/include/clang/AST/Decl.h > cfe/trunk/lib/CodeGen/CGExpr.cpp > cfe/trunk/lib/CodeGen/CGValue.h > cfe/trunk/lib/CodeGen/CodeGenFunction.h > cfe/trunk/lib/Sema/SemaDecl.cpp > cfe/trunk/test/Sema/asm.c > cfe/trunk/test/Sema/decl-invalid.c > > Modified: cfe/trunk/include/clang/AST/Decl.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=209149&r1=209148&r2=209149&view=diff============================================================================== > --- cfe/trunk/include/clang/AST/Decl.h (original) > +++ cfe/trunk/include/clang/AST/Decl.h Mon May 19 13:15:42 2014 > @@ -826,6 +826,10 @@ public: > // Second check is for C++11 [dcl.stc]p4. > return !isFileVarDecl() && getTSCSpec() == TSCS_unspecified; > > + // Global Named Register (GNU extension) > + if (getStorageClass() == SC_Register && !isLocalVarDecl()) > + return false; > + > // Return true for: Auto, Register. > // Return false for: Extern, Static, PrivateExtern, OpenCLWorkGroupLocal. > > > Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=209149&r1=209148&r2=209149&view=diff============================================================================== > --- cfe/trunk/lib/CodeGen/CGExpr.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGExpr.cpp Mon May 19 13:15:42 2014 > @@ -21,6 +21,7 @@ > #include "TargetInfo.h" > #include "clang/AST/ASTContext.h" > #include "clang/AST/DeclObjC.h" > +#include "clang/AST/Attr.h" > #include "clang/Frontend/CodeGenOptions.h" > #include "llvm/ADT/Hashing.h" > #include "llvm/IR/DataLayout.h" > @@ -1276,6 +1277,10 @@ RValue CodeGenFunction::EmitLoadOfLValue > if (LV.isExtVectorElt()) > return EmitLoadOfExtVectorElementLValue(LV); > > + // Global Register variables always invoke intrinsics > + if (LV.isGlobalReg()) > + return EmitLoadOfGlobalRegLValue(LV); > + > assert(LV.isBitField() && "Unknown LValue type!"); > return EmitLoadOfBitfieldLValue(LV); > } > @@ -1343,6 +1348,16 @@ RValue CodeGenFunction::EmitLoadOfExtVec > return RValue::get(Vec); > } > > +/// @brief Load of global gamed gegisters are always calls to intrinsics. > +RValue CodeGenFunction::EmitLoadOfGlobalRegLValue(LValue LV) { > + assert(LV.getType()->isIntegerType() && "Bad type for register variable"); > + llvm::MDNode *RegName = dyn_cast<llvm::MDNode>(LV.getGlobalReg()); > + assert(RegName && "Register LValue is not metadata"); > + llvm::Type *Types[] = { CGM.getTypes().ConvertType(LV.getType()) }; > + llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::read_register, Types); > + llvm::Value* Call = Builder.CreateCall(F, RegName); > + return RValue::get(Call); > +} > > > /// EmitStoreThroughLValue - Store the specified rvalue into the specified > @@ -1370,6 +1385,9 @@ void CodeGenFunction::EmitStoreThroughLV > if (Dst.isExtVectorElt()) > return EmitStoreThroughExtVectorComponentLValue(Src, Dst); > > + if (Dst.isGlobalReg()) > + return EmitStoreThroughGlobalRegLValue(Src, Dst); > + > assert(Dst.isBitField() && "Unknown LValue type"); > return EmitStoreThroughBitfieldLValue(Src, Dst); > } > @@ -1581,6 +1599,17 @@ void CodeGenFunction::EmitStoreThroughEx > Store->setAlignment(Dst.getAlignment().getQuantity()); > } > > +/// @brief Store of global named registers are always calls to intrinsics. > +void CodeGenFunction::EmitStoreThroughGlobalRegLValue(RValue Src, LValue > Dst) { > + assert(Dst.getType()->isIntegerType() && "Bad type for register variable"); > + llvm::MDNode *RegName = dyn_cast<llvm::MDNode>(Dst.getGlobalReg()); > + assert(RegName && "Register LValue is not metadata"); > + llvm::Type *Types[] = { CGM.getTypes().ConvertType(Dst.getType()) }; > + llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::write_register, Types); > + llvm::Value *Value = Src.getScalarVal(); > + Builder.CreateCall2(F, RegName, Value); > +} > + > // setObjCGCLValueClass - sets class of he lvalue for the purpose of > // generating write-barries API. It is currently a global, ivar, > // or neither. > @@ -1740,14 +1769,41 @@ static LValue EmitCapturedFieldLValue(Co > return CGF.EmitLValueForField(LV, FD); > } > > +/// Named Registers are named metadata pointing to the register name > +/// which will be read from/written to as an argument to the intrinsic > +/// @llvm.read/write_register. > +/// So far, only the name is being passed down, but other options such as > +/// register type, allocation type or even optimization options could be > +/// passed down via the metadata node. > +static LValue EmitGlobalNamedRegister(const VarDecl *VD, > + CodeGenModule &CGM, > + CharUnits Alignment) { > + AsmLabelAttr *Asm = VD->getAttr<AsmLabelAttr>(); > + llvm::Twine Name("llvm.named.register."+Asm->getLabel()); > + llvm::NamedMDNode *M = > CGM.getModule().getOrInsertNamedMetadata(Name.str()); > + if (M->getNumOperands() == 0) { > + llvm::MDString *Str = llvm::MDString::get(CGM.getLLVMContext(), > + Asm->getLabel()); > + llvm::Value *Ops[] = { Str }; > + M->addOperand(llvm::MDNode::get(CGM.getLLVMContext(), Ops)); > + } > + return LValue::MakeGlobalReg(M->getOperand(0), VD->getType(), Alignment); > +} > + > LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { > const NamedDecl *ND = E->getDecl(); > CharUnits Alignment = getContext().getDeclAlign(ND); > QualType T = E->getType(); > + const auto *VD = dyn_cast<VarDecl>(ND); > + > + // Global Named registers access via intrinsics only > + if (VD && VD->getStorageClass() == SC_Register && > + VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl()) > + return EmitGlobalNamedRegister(VD, CGM, Alignment); > > // A DeclRefExpr for a reference initialized by a constant expression can > // appear without being odr-used. Directly emit the constant initializer. > - if (const auto *VD = dyn_cast<VarDecl>(ND)) { > + if (VD) { > const Expr *Init = VD->getAnyInitializer(VD); > if (Init && !isa<ParmVarDecl>(VD) && VD->getType()->isReferenceType() && > VD->isUsableInConstantExpressions(getContext()) && > @@ -1773,7 +1829,7 @@ LValue CodeGenFunction::EmitDeclRefLValu > return MakeAddrLValue(Aliasee, T, Alignment); > } > > - if (const auto *VD = dyn_cast<VarDecl>(ND)) { > + if (VD) { > // Check if this is a global variable. > if (VD->hasLinkage() || VD->isStaticDataMember()) > return EmitGlobalVarDeclLValue(*this, E, VD); > > Modified: cfe/trunk/lib/CodeGen/CGValue.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGValue.h?rev=209149&r1=209148&r2=209149&view=diff============================================================================== > --- cfe/trunk/lib/CodeGen/CGValue.h (original) > +++ cfe/trunk/lib/CodeGen/CGValue.h Mon May 19 13:15:42 2014 > @@ -110,7 +110,8 @@ class LValue { > Simple, // This is a normal l-value, use getAddress(). > VectorElt, // This is a vector element l-value (V[i]), use getVector* > BitField, // This is a bitfield l-value, use getBitfield*. > - ExtVectorElt // This is an extended vector subset, use getExtVectorComp > + ExtVectorElt, // This is an extended vector subset, use getExtVectorComp > + GlobalReg // This is a register l-value, use getGlobalReg() > } LVType; > > llvm::Value *V; > @@ -192,6 +193,7 @@ public: > bool isVectorElt() const { return LVType == VectorElt; } > bool isBitField() const { return LVType == BitField; } > bool isExtVectorElt() const { return LVType == ExtVectorElt; } > + bool isGlobalReg() const { return LVType == GlobalReg; } > > bool isVolatileQualified() const { return Quals.hasVolatile(); } > bool isRestrictQualified() const { return Quals.hasRestrict(); } > @@ -286,6 +288,9 @@ public: > return *BitFieldInfo; > } > > + // global register lvalue > + llvm::Value *getGlobalReg() const { assert(isGlobalReg()); return V; } > + > static LValue MakeAddr(llvm::Value *address, QualType type, > CharUnits alignment, ASTContext &Context, > llvm::MDNode *TBAAInfo = 0) { > @@ -335,6 +340,16 @@ public: > R.Initialize(type, type.getQualifiers(), Alignment); > return R; > } > + > + static LValue MakeGlobalReg(llvm::Value *Reg, > + QualType type, > + CharUnits Alignment) { > + LValue R; > + R.LVType = GlobalReg; > + R.V = Reg; > + R.Initialize(type, type.getQualifiers(), Alignment); > + return R; > + } > > RValue asAggregateRValue() const { > // FIMXE: Alignment > > Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=209149&r1=209148&r2=209149&view=diff============================================================================== > --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original) > +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Mon May 19 13:15:42 2014 > @@ -1979,12 +1979,14 @@ public: > RValue EmitLoadOfLValue(LValue V, SourceLocation Loc); > RValue EmitLoadOfExtVectorElementLValue(LValue V); > RValue EmitLoadOfBitfieldLValue(LValue LV); > + RValue EmitLoadOfGlobalRegLValue(LValue LV); > > /// EmitStoreThroughLValue - Store the specified rvalue into the specified > /// lvalue, where both are guaranteed to the have the same type, and that > type > /// is 'Ty'. > void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false); > void EmitStoreThroughExtVectorComponentLValue(RValue Src, LValue Dst); > + void EmitStoreThroughGlobalRegLValue(RValue Src, LValue Dst); > > /// EmitStoreThroughBitfieldLValue - Store Src into Dst with same > constraints > /// as EmitStoreThroughLValue. > @@ -2009,6 +2011,7 @@ public: > // Note: only available for agg return types > LValue EmitVAArgExprLValue(const VAArgExpr *E); > LValue EmitDeclRefLValue(const DeclRefExpr *E); > + LValue EmitReadRegister(const VarDecl *VD); > LValue EmitStringLiteralLValue(const StringLiteral *E); > LValue EmitObjCEncodeExprLValue(const ObjCEncodeExpr *E); > LValue EmitPredefinedLValue(const PredefinedExpr *E); > > Modified: cfe/trunk/lib/Sema/SemaDecl.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=209149&r1=209148&r2=209149&view=diff============================================================================== > --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) > +++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon May 19 13:15:42 2014 > @@ -5119,13 +5119,9 @@ Sema::ActOnVariableDeclarator(Scope *S, > if (!DC->isRecord() && S->getFnParent() == 0) { > // C99 6.9p2: The storage-class specifiers auto and register shall not > // appear in the declaration specifiers in an external declaration. > - if (SC == SC_Auto || SC == SC_Register) { > - // If this is a register variable with an asm label specified, then > this > - // is a GNU extension. > - if (SC == SC_Register && D.getAsmLabel()) > - Diag(D.getIdentifierLoc(), diag::err_unsupported_global_register); > - else > - Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope); > + // Global Register+Asm is a GNU extension we support. > + if (SC == SC_Auto || (SC == SC_Register && !D.getAsmLabel())) { > + Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope); > D.setInvalidType(); > } > } > @@ -5437,6 +5433,7 @@ Sema::ActOnVariableDeclarator(Scope *S, > Diag(E->getExprLoc(), diag::warn_asm_label_on_auto_decl) << Label; > break; > case SC_Register: > + // Local Named register > if (!Context.getTargetInfo().isValidGCCRegisterName(Label)) > Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << > Label; > break; > @@ -5446,6 +5443,10 @@ Sema::ActOnVariableDeclarator(Scope *S, > case SC_OpenCLWorkGroupLocal: > break; > } > + } else if (SC == SC_Register) { > + // Global Named register > + if (!Context.getTargetInfo().isValidGCCRegisterName(Label)) > + Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label; > } > > NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), > > Added: cfe/trunk/test/CodeGen/named_reg_global.c > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/named_reg_global.c?rev=209149&view=auto============================================================================== > --- cfe/trunk/test/CodeGen/named_reg_global.c (added) > +++ cfe/trunk/test/CodeGen/named_reg_global.c Mon May 19 13:15:42 2014 > @@ -0,0 +1,26 @@ > +// RUN: %clang_cc1 -triple x86_64-linux-gnu -S -emit-llvm %s -o - | > FileCheck %s > +// RUN: %clang_cc1 -triple aarch64-linux-gnu -S -emit-llvm %s -o - | > FileCheck %s > +// RUN: %clang_cc1 -triple arm64-linux-gnu -S -emit-llvm %s -o - | FileCheck > %s > +// RUN: %clang_cc1 -triple armv7-linux-gnu -S -emit-llvm %s -o - | FileCheck > %s > + > +register unsigned long current_stack_pointer asm("sp"); > + > +// CHECK: define{{.*}} i[[bits:[0-9]+]] @get_stack_pointer_addr() > +// CHECK: [[ret:%[0-9]+]] = call i[[bits]] > @llvm.read_register.i[[bits]](metadata !0) > +// CHECK: ret i[[bits]] [[ret]] > +unsigned long get_stack_pointer_addr() { > + return current_stack_pointer; > +} > +// CHECK: declare{{.*}} i[[bits]] @llvm.read_register.i[[bits]](metadata) > + > +// CHECK: define{{.*}} void @set_stack_pointer_addr(i[[bits]] %addr) #0 { > +// CHECK: [[sto:%[0-9]+]] = load i[[bits]]* %addr > +// CHECK: call void @llvm.write_register.i[[bits]](metadata !0, i[[bits]] > [[sto]]) > +// CHECK: ret void > +void set_stack_pointer_addr(unsigned long addr) { > + current_stack_pointer = addr; > +} > +// CHECK: declare{{.*}} void @llvm.write_register.i[[bits]](metadata, > i[[bits]]) > + > +// CHECK: !llvm.named.register.sp = !{!0} > +// CHECK: !0 = metadata !{metadata !"sp"} > > Modified: cfe/trunk/test/Sema/asm.c > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/asm.c?rev=209149&r1=209148&r2=209149&view=diff============================================================================== > --- cfe/trunk/test/Sema/asm.c (original) > +++ cfe/trunk/test/Sema/asm.c Mon May 19 13:15:42 2014 > @@ -95,8 +95,6 @@ void test9(int i) { > asm("" : [foo] "=r" (i), "=r"(i) : "[foo]1"(i)); // > expected-error{{invalid input constraint '[foo]1' in asm}} > } > > -register int g asm("dx"); // expected-error{{global register variables are > not supported}} > - > void test10(void){ > static int g asm ("g_asm") = 0; > extern int gg asm ("gg_asm"); > > Modified: cfe/trunk/test/Sema/decl-invalid.c > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/decl-invalid.c?rev=209149&r1=209148&r2=209149&view=diff============================================================================== > --- cfe/trunk/test/Sema/decl-invalid.c (original) > +++ cfe/trunk/test/Sema/decl-invalid.c Mon May 19 13:15:42 2014 > @@ -24,5 +24,4 @@ I; // expected-warning {{declaration doe > > // rdar://6880449 > register int test1; // expected-error {{illegal storage class on > file-scoped variable}} > -register int test2 __asm__("edi"); // expected-error {{global register > variables are not supported}} > > > > _______________________________________________ > cfe-commits mailing list > cfe-commits@cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list cfe-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits