Index: test/Transforms/EarlyCSE/asm-const-type-qualifier.ll =================================================================== --- test/Transforms/EarlyCSE/asm-const-type-qualifier.ll (revision 0) +++ test/Transforms/EarlyCSE/asm-const-type-qualifier.ll (revision 0) @@ -0,0 +1,24 @@ +; RUN: opt < %s -S -early-cse | FileCheck %s + +; Check to make sure the second inline asm is CSE'ed. +; CHECK: @fn +; CHECK: %0 = tail call i8* asm constant "mov $$0x12345678, $0", "=r,~{dirflag},~{fpsr},~{flags}"() nounwind readnone +; CHECK-NOT: call i8* asm constant "mov $$0x12345678, $0", "=r,~{dirflag},~{fpsr},~{flags}"() nounwind readnone +define void @fn() nounwind ssp { +entry: + %0 = tail call i8* asm constant "mov $$0x12345678, $0", "=r,~{dirflag},~{fpsr},~{flags}"() nounwind readnone + %1 = bitcast i8* %0 to i8** + %2 = load i8** %1, align 8 + %tobool = icmp eq i8* %2, null + br i1 %tobool, label %if.end, label %if.then + +if.then: ; preds = %entry + %3 = tail call i8* asm constant "mov $$0x12345678, $0", "=r,~{dirflag},~{fpsr},~{flags}"() nounwind readnone + %4 = bitcast i8* %3 to i8** + store i8* null, i8** %4, align 8 + br label %if.end + +if.end: ; preds = %entry, %if.then + ret void +} + Index: test/Assembler/alignstack.ll =================================================================== --- test/Assembler/alignstack.ll (revision 156383) +++ test/Assembler/alignstack.ll (working copy) @@ -5,6 +5,7 @@ define void @test1() nounwind { ; CHECK: test1 ; CHECK: sideeffect +; CHECK-NOT: constant ; CHECK-NOT: alignstack tail call void asm sideeffect "mov", "~{dirflag},~{fpsr},~{flags}"() nounwind ret void @@ -13,6 +14,7 @@ define void @test2() nounwind { ; CHECK: test2 ; CHECK: sideeffect +; CHECK-NOT: constant ; CHECK: alignstack tail call void asm sideeffect alignstack "mov", "~{dirflag},~{fpsr},~{flags}"() nounwind ret void @@ -21,6 +23,7 @@ define void @test3() nounwind { ; CHECK: test3 ; CHECK-NOT: sideeffect +; CHECK-NOT: constant ; CHECK: alignstack tail call void asm alignstack "mov", "~{dirflag},~{fpsr},~{flags}"() nounwind ret void @@ -29,8 +32,27 @@ define void @test4() nounwind { ; CHECK: test4 ; CHECK-NOT: sideeffect +; CHECK-NOT: constant ; CHECK-NOT: alignstack tail call void asm "mov", "~{dirflag},~{fpsr},~{flags}"() nounwind ret void ; CHECK: ret } +define void @test5() nounwind { +; CHECK: test5 +; CHECK-NOT: sideeffect +; CHECK: constant +; CHECK-NOT: alignstack + tail call void asm constant "mov", "~{dirflag},~{fpsr},~{flags}"() nounwind readnone + ret void +; CHECK: ret +} +define void @test6() nounwind { +; CHECK: test6 +; CHECK-NOT: sideeffect +; CHECK: constant +; CHECK: alignstack + tail call void asm constant alignstack "mov", "~{dirflag},~{fpsr},~{flags}"() nounwind readnone + ret void +; CHECK: ret +} Index: include/llvm/InlineAsm.h =================================================================== --- include/llvm/InlineAsm.h (revision 156383) +++ include/llvm/InlineAsm.h (working copy) @@ -43,10 +43,11 @@ std::string AsmString, Constraints; bool HasSideEffects; bool IsAlignStack; - + bool IsConst; + InlineAsm(PointerType *Ty, const std::string &AsmString, const std::string &Constraints, bool hasSideEffects, - bool isAlignStack); + bool isAlignStack, bool isConst); virtual ~InlineAsm(); /// When the ConstantUniqueMap merges two types and makes two InlineAsms @@ -58,10 +59,11 @@ /// static InlineAsm *get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, - bool isAlignStack = false); + bool isAlignStack = false, bool isConst = false); bool hasSideEffects() const { return HasSideEffects; } bool isAlignStack() const { return IsAlignStack; } + bool isConst() const { return IsConst; } /// getType - InlineAsm's are always pointers. /// @@ -193,17 +195,18 @@ Op_InputChain = 0, Op_AsmString = 1, Op_MDNode = 2, - Op_ExtraInfo = 3, // HasSideEffects, IsAlignStack + Op_ExtraInfo = 3, // HasSideEffects, IsAlignStack, IsConst Op_FirstOperand = 4, // Fixed operands on an INLINEASM MachineInstr. MIOp_AsmString = 0, - MIOp_ExtraInfo = 1, // HasSideEffects, IsAlignStack + MIOp_ExtraInfo = 1, // HasSideEffects, IsAlignStack, IsConst MIOp_FirstOperand = 2, // Interpretation of the MIOp_ExtraInfo bit field. Extra_HasSideEffects = 1, Extra_IsAlignStack = 2, + Extra_IsConst = 3, // Inline asm operands map to multiple SDNode / MachineInstr operands. // The first operand is an immediate describing the asm operand, the low Index: lib/VMCore/AsmWriter.cpp =================================================================== --- lib/VMCore/AsmWriter.cpp (revision 156383) +++ lib/VMCore/AsmWriter.cpp (working copy) @@ -1014,6 +1014,8 @@ Out << "asm "; if (IA->hasSideEffects()) Out << "sideeffect "; + if (IA->isConst()) + Out << "constant "; if (IA->isAlignStack()) Out << "alignstack "; Out << '"'; Index: lib/VMCore/InlineAsm.cpp =================================================================== --- lib/VMCore/InlineAsm.cpp (revision 156383) +++ lib/VMCore/InlineAsm.cpp (working copy) @@ -27,19 +27,20 @@ InlineAsm *InlineAsm::get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, - bool isAlignStack) { - InlineAsmKeyType Key(AsmString, Constraints, hasSideEffects, isAlignStack); + bool isAlignStack, bool isConst) { + InlineAsmKeyType Key(AsmString, Constraints, hasSideEffects, isAlignStack, + isConst); LLVMContextImpl *pImpl = Ty->getContext().pImpl; return pImpl->InlineAsms.getOrCreate(PointerType::getUnqual(Ty), Key); } InlineAsm::InlineAsm(PointerType *Ty, const std::string &asmString, const std::string &constraints, bool hasSideEffects, - bool isAlignStack) + bool isAlignStack, bool isConst) : Value(Ty, Value::InlineAsmVal), AsmString(asmString), - Constraints(constraints), HasSideEffects(hasSideEffects), - IsAlignStack(isAlignStack) { + Constraints(constraints), HasSideEffects(hasSideEffects), + IsAlignStack(isAlignStack), IsConst(isConst) { // Do various checks on the constraint string and type. assert(Verify(getFunctionType(), constraints) && Index: lib/VMCore/ConstantsContext.h =================================================================== --- lib/VMCore/ConstantsContext.h (revision 156383) +++ lib/VMCore/ConstantsContext.h (working copy) @@ -352,18 +352,21 @@ struct InlineAsmKeyType { InlineAsmKeyType(StringRef AsmString, StringRef Constraints, bool hasSideEffects, - bool isAlignStack) + bool isAlignStack, bool isConst) : asm_string(AsmString), constraints(Constraints), - has_side_effects(hasSideEffects), is_align_stack(isAlignStack) {} + has_side_effects(hasSideEffects), is_align_stack(isAlignStack), + is_const(isConst) {} std::string asm_string; std::string constraints; bool has_side_effects; bool is_align_stack; + bool is_const; bool operator==(const InlineAsmKeyType& that) const { return this->asm_string == that.asm_string && this->constraints == that.constraints && this->has_side_effects == that.has_side_effects && - this->is_align_stack == that.is_align_stack; + this->is_align_stack == that.is_align_stack && + this->is_const == that.is_const; } bool operator<(const InlineAsmKeyType& that) const { if (this->asm_string != that.asm_string) @@ -374,6 +377,8 @@ return this->has_side_effects < that.has_side_effects; if (this->is_align_stack != that.is_align_stack) return this->is_align_stack < that.is_align_stack; + if (this->is_const != that.is_const) + return this->is_const < that.is_const; return false; } @@ -490,7 +495,7 @@ struct ConstantCreator { static InlineAsm *create(PointerType *Ty, const InlineAsmKeyType &Key) { return new InlineAsm(Ty, Key.asm_string, Key.constraints, - Key.has_side_effects, Key.is_align_stack); + Key.has_side_effects, Key.is_align_stack,Key.is_const); } }; @@ -499,7 +504,8 @@ typedef InlineAsmKeyType ValType; static ValType getValType(InlineAsm *Asm) { return InlineAsmKeyType(Asm->getAsmString(), Asm->getConstraintString(), - Asm->hasSideEffects(), Asm->isAlignStack()); + Asm->hasSideEffects(), Asm->isAlignStack(), + Asm->isConst()); } }; Index: lib/AsmParser/LLParser.cpp =================================================================== --- lib/AsmParser/LLParser.cpp (revision 156383) +++ lib/AsmParser/LLParser.cpp (working copy) @@ -2025,17 +2025,20 @@ return false; case lltok::kw_asm: { - // ValID ::= 'asm' SideEffect? AlignStack? STRINGCONSTANT ',' STRINGCONSTANT - bool HasSideEffect, AlignStack; + // ValID ::= 'asm' [SideEffect|IsConst]? AlignStack? STRINGCONSTANT ',' + // STRINGCONSTANT + bool HasSideEffect, AlignStack, IsConst; Lex.Lex(); if (ParseOptionalToken(lltok::kw_sideeffect, HasSideEffect) || + ParseOptionalToken(lltok::kw_constant, IsConst) || ParseOptionalToken(lltok::kw_alignstack, AlignStack) || ParseStringConstant(ID.StrVal) || ParseToken(lltok::comma, "expected comma in inline asm expression") || ParseToken(lltok::StringConstant, "expected constraint string")) return true; ID.StrVal2 = Lex.getStrVal(); - ID.UIntVal = unsigned(HasSideEffect) | (unsigned(AlignStack)<<1); + ID.UIntVal = unsigned(HasSideEffect) | (unsigned(AlignStack)<<1) | + (unsigned(IsConst)<<2); ID.Kind = ValID::t_InlineAsm; return false; } @@ -2452,7 +2455,8 @@ PTy ? dyn_cast(PTy->getElementType()) : 0; if (!FTy || !InlineAsm::Verify(FTy, ID.StrVal2)) return Error(ID.Loc, "invalid type for inline asm constraint string"); - V = InlineAsm::get(FTy, ID.StrVal, ID.StrVal2, ID.UIntVal&1, ID.UIntVal>>1); + V = InlineAsm::get(FTy, ID.StrVal, ID.StrVal2, ID.UIntVal & 1, + (ID.UIntVal >> 1) & 1, (ID.UIntVal >> 2) & 1); return false; } case ValID::t_MDNode: Index: lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp (revision 156383) +++ lib/Bitcode/Reader/BitcodeReader.cpp (working copy) @@ -1274,7 +1274,8 @@ if (Record.size() < 2) return Error("Invalid INLINEASM record"); std::string AsmStr, ConstrStr; bool HasSideEffects = Record[0] & 1; - bool IsAlignStack = Record[0] >> 1; + bool IsAlignStack = (Record[0] >> 1) & 1; + bool IsConst = (Record[0] >> 2) & 1; unsigned AsmStrSize = Record[1]; if (2+AsmStrSize >= Record.size()) return Error("Invalid INLINEASM record"); @@ -1288,7 +1289,7 @@ ConstrStr += (char)Record[3+AsmStrSize+i]; PointerType *PTy = cast(CurTy); V = InlineAsm::get(cast(PTy->getElementType()), - AsmStr, ConstrStr, HasSideEffects, IsAlignStack); + AsmStr, ConstrStr, HasSideEffects, IsAlignStack, IsConst); break; } case bitc::CST_CODE_BLOCKADDRESS:{ Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp (revision 156383) +++ lib/Bitcode/Writer/BitcodeWriter.cpp (working copy) @@ -776,7 +776,8 @@ if (const InlineAsm *IA = dyn_cast(V)) { Record.push_back(unsigned(IA->hasSideEffects()) | - unsigned(IA->isAlignStack()) << 1); + (unsigned(IA->isAlignStack()) << 1) | + (unsigned(IA->isConst()) << 2)); // Add the asm string. const std::string &AsmStr = IA->getAsmString();