Index: lib/CodeGen/SelectionDAG/LegalizeDAG.cpp =================================================================== --- lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -156,6 +156,8 @@ // Node replacement helpers void ReplacedNode(SDNode *N) { LegalizedNodes.erase(N); + if (UpdatedNodes) + UpdatedNodes->insert(N); } void ReplaceNode(SDNode *Old, SDNode *New) { DEBUG(dbgs() << " ... replacing: "; Old->dump(&DAG); Index: lib/Support/Unix/Path.inc =================================================================== --- lib/Support/Unix/Path.inc +++ lib/Support/Unix/Path.inc @@ -663,7 +663,7 @@ static const char *getDefaultTempDir(bool ErasedOnReboot) { #ifdef P_tmpdir - if (P_tmpdir) + if ((bool)P_tmpdir) return P_tmpdir; #endif Index: lib/Target/X86/AsmParser/CMakeLists.txt =================================================================== --- lib/Target/X86/AsmParser/CMakeLists.txt +++ lib/Target/X86/AsmParser/CMakeLists.txt @@ -2,3 +2,5 @@ X86AsmInstrumentation.cpp X86AsmParser.cpp ) + +target_link_libraries(LLVMX86AsmParser LLVMX86CodeGen) Index: lib/Target/X86/AsmParser/X86AsmInstrumentation.h =================================================================== --- lib/Target/X86/AsmParser/X86AsmInstrumentation.h +++ lib/Target/X86/AsmParser/X86AsmInstrumentation.h @@ -37,7 +37,7 @@ // Tries to instrument and emit instruction. virtual void InstrumentAndEmitInstruction( const MCInst &Inst, - SmallVectorImpl> &Operands, + SmallVectorImpl > &Operands, MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out); protected: Index: lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp =================================================================== --- lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp +++ lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp @@ -10,8 +10,10 @@ #include "MCTargetDesc/X86BaseInfo.h" #include "X86AsmInstrumentation.h" #include "X86Operand.h" +#include "X86RegisterInfo.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Triple.h" +#include "llvm/CodeGen/MachineValueType.h" #include "llvm/IR/Function.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCInst.h" @@ -36,6 +38,8 @@ return Reg == X86::RSP || Reg == X86::ESP || Reg == X86::SP; } +bool IsSmallMemAccess(unsigned AccessSize) { return AccessSize < 8; } + std::string FuncName(unsigned AccessSize, bool IsWrite) { return std::string("__asan_report_") + (IsWrite ? "store" : "load") + utostr(AccessSize); @@ -43,14 +47,41 @@ class X86AddressSanitizer : public X86AsmInstrumentation { public: + struct AsanContext { + AsanContext(unsigned AccessSize, bool IsWrite) + : AddressReg(X86::RDI), ShadowReg(X86::RAX), + ExpectedShadowValueReg(X86::RCX), AccessSize(AccessSize), + IsWrite(IsWrite) {} + + unsigned addressReg(MVT::SimpleValueType VT) const { + return getX86SubSuperRegister(AddressReg, VT); + } + + unsigned shadowReg(MVT::SimpleValueType VT) const { + return getX86SubSuperRegister(ShadowReg, VT); + } + + unsigned expectedShadowValueReg(MVT::SimpleValueType VT) const { + return getX86SubSuperRegister(ExpectedShadowValueReg, VT); + } + + unsigned AddressReg; + unsigned ShadowReg; + unsigned ExpectedShadowValueReg; + unsigned AccessSize; + bool IsWrite; + }; + X86AddressSanitizer(const MCSubtargetInfo &STI) : X86AsmInstrumentation(STI), RepPrefix(false) {} virtual ~X86AddressSanitizer() {} // X86AsmInstrumentation implementation: - virtual void InstrumentAndEmitInstruction( - const MCInst &Inst, OperandVector &Operands, MCContext &Ctx, - const MCInstrInfo &MII, MCStreamer &Out) override { + virtual void InstrumentAndEmitInstruction(const MCInst &Inst, + OperandVector &Operands, + MCContext &Ctx, + const MCInstrInfo &MII, + MCStreamer &Out) override { InstrumentMOVS(Inst, Operands, Ctx, MII, Out); if (RepPrefix) EmitInstruction(Out, MCInstBuilder(X86::REP_PREFIX)); @@ -63,65 +94,97 @@ } // Should be implemented differently in x86_32 and x86_64 subclasses. - virtual void InstrumentMemOperandSmallImpl( - X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, - MCStreamer &Out) = 0; - virtual void InstrumentMemOperandLargeImpl( - X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, - MCStreamer &Out) = 0; + virtual void StoreFlags(MCStreamer &Out) = 0; + + virtual void RestoreFlags(MCStreamer &Out) = 0; + + // Adjusts up stack and saves all registers used in instrumentation. + virtual void InstrumentMemOperandPrologue(const AsanContext &AsanCtx, + MCContext &Ctx, + MCStreamer &Out) = 0; + + // Restores all registers used in instrumentation and adjusts stack. + virtual void InstrumentMemOperandEpilogue(const AsanContext &AsanCtx, + MCContext &Ctx, + MCStreamer &Out) = 0; + + virtual void InstrumentMemOperandSmall(X86Operand &Op, + const AsanContext &AsanCtx, + MCContext &Ctx, MCStreamer &Out) = 0; + virtual void InstrumentMemOperandLarge(X86Operand &Op, + const AsanContext &AsanCtx, + MCContext &Ctx, MCStreamer &Out) = 0; + virtual void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx, MCStreamer &Out) = 0; - void InstrumentMemOperand(MCParsedAsmOperand &Op, unsigned AccessSize, - bool IsWrite, MCContext &Ctx, MCStreamer &Out); + void InstrumentMemOperandAny(X86Operand &Op, const AsanContext &AsanCtx, + MCContext &Ctx, MCStreamer &Out); + void InstrumentMemOperand(X86Operand &Op, const AsanContext &AsanCtx, + MCContext &Ctx, MCStreamer &Out); void InstrumentMOVSBase(unsigned DstReg, unsigned SrcReg, unsigned CntReg, unsigned AccessSize, MCContext &Ctx, MCStreamer &Out); + void InstrumentMOVS(const MCInst &Inst, OperandVector &Operands, MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out); void InstrumentMOV(const MCInst &Inst, OperandVector &Operands, MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out); +protected: void EmitLabel(MCStreamer &Out, MCSymbol *Label) { Out.EmitLabel(Label); } -protected: // True when previous instruction was actually REP prefix. bool RepPrefix; }; -void X86AddressSanitizer::InstrumentMemOperand( - MCParsedAsmOperand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, - MCStreamer &Out) { +void X86AddressSanitizer::InstrumentMemOperandAny(X86Operand &Op, + const AsanContext &AsanCtx, + MCContext &Ctx, + MCStreamer &Out) { + unsigned AccessSize = AsanCtx.AccessSize; + assert(Op.isMem() && "Op should be a memory operand."); assert((AccessSize & (AccessSize - 1)) == 0 && AccessSize <= 16 && "AccessSize should be a power of two, less or equal than 16."); + // FIXME: take into account load/store alignment. + if (IsSmallMemAccess(AccessSize)) + InstrumentMemOperandSmall(Op, AsanCtx, Ctx, Out); + else + InstrumentMemOperandLarge(Op, AsanCtx, Ctx, Out); +} - X86Operand &MemOp = static_cast(Op); +void X86AddressSanitizer::InstrumentMemOperand(X86Operand &Op, + const AsanContext &AsanCtx, + MCContext &Ctx, + MCStreamer &Out) { // FIXME: get rid of this limitation. - if (IsStackReg(MemOp.getMemBaseReg()) || IsStackReg(MemOp.getMemIndexReg())) + if (IsStackReg(Op.getMemBaseReg()) || IsStackReg(Op.getMemIndexReg())) return; - // FIXME: take into account load/store alignment. - if (AccessSize < 8) - InstrumentMemOperandSmallImpl(MemOp, AccessSize, IsWrite, Ctx, Out); - else - InstrumentMemOperandLargeImpl(MemOp, AccessSize, IsWrite, Ctx, Out); + InstrumentMemOperandPrologue(AsanCtx, Ctx, Out); + InstrumentMemOperandAny(Op, AsanCtx, Ctx, Out); + InstrumentMemOperandEpilogue(AsanCtx, Ctx, Out); } -void X86AddressSanitizer::InstrumentMOVSBase( - unsigned DstReg, unsigned SrcReg, unsigned CntReg, unsigned AccessSize, - MCContext &Ctx, MCStreamer &Out) { +void X86AddressSanitizer::InstrumentMOVSBase(unsigned DstReg, unsigned SrcReg, + unsigned CntReg, + unsigned AccessSize, + MCContext &Ctx, MCStreamer &Out) { // FIXME: check whole ranges [DstReg .. DstReg + AccessSize * (CntReg - 1)] // and [SrcReg .. SrcReg + AccessSize * (CntReg - 1)]. + AsanContext AsanCtx(AccessSize, false /* IsWrite */); + AsanCtx.AddressReg = X86::RDX; + AsanCtx.ShadowReg = X86::RAX; + AsanCtx.ExpectedShadowValueReg = X86::RBX; - // FIXME: extract prolog and epilogue from InstrumentMemOperand() - // and optimize this sequence of InstrumentMemOperand() calls. + InstrumentMemOperandPrologue(AsanCtx, Ctx, Out); // Test (%SrcReg) { const MCExpr *Disp = MCConstantExpr::Create(0, Ctx); std::unique_ptr Op(X86Operand::CreateMem( - 0, Disp, SrcReg, 0, AccessSize, SMLoc(), SMLoc())); - InstrumentMemOperand(*Op, AccessSize, false /* IsWrite */, Ctx, Out); + 0, Disp, SrcReg, 0, AsanCtx.AccessSize, SMLoc(), SMLoc())); + InstrumentMemOperandAny(*Op, AsanCtx, Ctx, Out); } // Test -1(%SrcReg, %CntReg, AccessSize) @@ -129,15 +192,17 @@ const MCExpr *Disp = MCConstantExpr::Create(-1, Ctx); std::unique_ptr Op(X86Operand::CreateMem( 0, Disp, SrcReg, CntReg, AccessSize, SMLoc(), SMLoc())); - InstrumentMemOperand(*Op, AccessSize, false /* IsWrite */, Ctx, Out); + InstrumentMemOperandAny(*Op, AsanCtx, Ctx, Out); } + AsanCtx.IsWrite = true; + // Test (%DstReg) { const MCExpr *Disp = MCConstantExpr::Create(0, Ctx); std::unique_ptr Op(X86Operand::CreateMem( 0, Disp, DstReg, 0, AccessSize, SMLoc(), SMLoc())); - InstrumentMemOperand(*Op, AccessSize, true /* IsWrite */, Ctx, Out); + InstrumentMemOperandAny(*Op, AsanCtx, Ctx, Out); } // Test -1(%DstReg, %CntReg, AccessSize) @@ -145,13 +210,16 @@ const MCExpr *Disp = MCConstantExpr::Create(-1, Ctx); std::unique_ptr Op(X86Operand::CreateMem( 0, Disp, DstReg, CntReg, AccessSize, SMLoc(), SMLoc())); - InstrumentMemOperand(*Op, AccessSize, true /* IsWrite */, Ctx, Out); + InstrumentMemOperandAny(*Op, AsanCtx, Ctx, Out); } + + InstrumentMemOperandEpilogue(AsanCtx, Ctx, Out); } -void X86AddressSanitizer::InstrumentMOVS( - const MCInst &Inst, OperandVector &Operands, MCContext &Ctx, - const MCInstrInfo &MII, MCStreamer &Out) { +void X86AddressSanitizer::InstrumentMOVS(const MCInst &Inst, + OperandVector &Operands, + MCContext &Ctx, const MCInstrInfo &MII, + MCStreamer &Out) { // Access size in bytes. unsigned AccessSize = 0; @@ -175,9 +243,10 @@ InstrumentMOVSImpl(AccessSize, Ctx, Out); } -void X86AddressSanitizer::InstrumentMOV( - const MCInst &Inst, OperandVector &Operands, MCContext &Ctx, - const MCInstrInfo &MII, MCStreamer &Out) { +void X86AddressSanitizer::InstrumentMOV(const MCInst &Inst, + OperandVector &Operands, MCContext &Ctx, + const MCInstrInfo &MII, + MCStreamer &Out) { // Access size in bytes. unsigned AccessSize = 0; @@ -216,8 +285,11 @@ for (unsigned Ix = 0; Ix < Operands.size(); ++Ix) { assert(Operands[Ix]); MCParsedAsmOperand &Op = *Operands[Ix]; - if (Op.isMem()) - InstrumentMemOperand(Op, AccessSize, IsWrite, Ctx, Out); + if (Op.isMem()) { + X86Operand &MemOp = static_cast(Op); + AsanContext AsanCtx(AccessSize, IsWrite); + InstrumentMemOperand(MemOp, AsanCtx, Ctx, Out); + } } } @@ -229,26 +301,67 @@ : X86AddressSanitizer(STI) {} virtual ~X86AddressSanitizer32() {} - virtual void InstrumentMemOperandSmallImpl( - X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, - MCStreamer &Out) override; - virtual void InstrumentMemOperandLargeImpl( - X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, - MCStreamer &Out) override; + virtual void StoreFlags(MCStreamer &Out) override { + EmitInstruction(Out, MCInstBuilder(X86::PUSHF32)); + } + + virtual void RestoreFlags(MCStreamer &Out) override { + EmitInstruction(Out, MCInstBuilder(X86::POPF32)); + } + + virtual void InstrumentMemOperandPrologue(const AsanContext &AsanCtx, + MCContext &Ctx, + MCStreamer &Out) override { + EmitInstruction( + Out, MCInstBuilder(X86::PUSH32r).addReg(AsanCtx.addressReg(MVT::i32))); + EmitInstruction( + Out, MCInstBuilder(X86::PUSH32r).addReg(AsanCtx.shadowReg(MVT::i32))); + if (IsSmallMemAccess(AsanCtx.AccessSize)) { + EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg( + AsanCtx.expectedShadowValueReg(MVT::i32))); + } + StoreFlags(Out); + } + + virtual void InstrumentMemOperandEpilogue(const AsanContext &AsanCtx, + MCContext &Ctx, + MCStreamer &Out) override { + RestoreFlags(Out); + if (IsSmallMemAccess(AsanCtx.AccessSize)) { + EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg( + AsanCtx.expectedShadowValueReg(MVT::i32))); + } + EmitInstruction( + Out, MCInstBuilder(X86::POP32r).addReg(AsanCtx.shadowReg(MVT::i32))); + EmitInstruction( + Out, MCInstBuilder(X86::POP32r).addReg(AsanCtx.addressReg(MVT::i32))); + } + + virtual void InstrumentMemOperandSmall(X86Operand &Op, + const AsanContext &AsanCtx, + MCContext &Ctx, + MCStreamer &Out) override; + virtual void InstrumentMemOperandLarge(X86Operand &Op, + const AsanContext &AsanCtx, + MCContext &Ctx, + MCStreamer &Out) override; virtual void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx, MCStreamer &Out) override; - private: - void EmitCallAsanReport(MCContext &Ctx, MCStreamer &Out, unsigned AccessSize, - bool IsWrite, unsigned AddressReg) { +private: + void EmitCallAsanReport(MCContext &Ctx, MCStreamer &Out, + const AsanContext &AsanCtx) { EmitInstruction(Out, MCInstBuilder(X86::CLD)); EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS)); - EmitInstruction(Out, MCInstBuilder(X86::AND64ri8).addReg(X86::ESP) - .addReg(X86::ESP).addImm(-16)); - EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(AddressReg)); + EmitInstruction(Out, MCInstBuilder(X86::AND64ri8) + .addReg(X86::ESP) + .addReg(X86::ESP) + .addImm(-16)); + EmitInstruction( + Out, MCInstBuilder(X86::PUSH32r).addReg(AsanCtx.addressReg(MVT::i32))); - const std::string &Fn = FuncName(AccessSize, IsWrite); + const std::string &Fn = FuncName(AsanCtx.AccessSize, AsanCtx.IsWrite); MCSymbol *FnSym = Ctx.GetOrCreateSymbol(StringRef(Fn)); const MCSymbolRefExpr *FnExpr = MCSymbolRefExpr::Create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx); @@ -256,67 +369,74 @@ } }; -void X86AddressSanitizer32::InstrumentMemOperandSmallImpl( - X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, +void X86AddressSanitizer32::InstrumentMemOperandSmall( + X86Operand &Op, const AsanContext &AsanCtx, MCContext &Ctx, MCStreamer &Out) { - EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::EAX)); - EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::ECX)); - EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::EDX)); - EmitInstruction(Out, MCInstBuilder(X86::PUSHF32)); + unsigned AddressRegI32 = AsanCtx.addressReg(MVT::i32); + unsigned ShadowRegI32 = AsanCtx.shadowReg(MVT::i32); + unsigned ShadowRegI8 = AsanCtx.shadowReg(MVT::i8); + unsigned ExpectedShadowValueRegI32 = AsanCtx.expectedShadowValueReg(MVT::i32); { MCInst Inst; Inst.setOpcode(X86::LEA32r); - Inst.addOperand(MCOperand::CreateReg(X86::EAX)); + Inst.addOperand(MCOperand::CreateReg(AddressRegI32)); Op.addMemOperands(Inst, 5); EmitInstruction(Out, Inst); } - EmitInstruction( - Out, MCInstBuilder(X86::MOV32rr).addReg(X86::ECX).addReg(X86::EAX)); - EmitInstruction(Out, MCInstBuilder(X86::SHR32ri).addReg(X86::ECX) - .addReg(X86::ECX).addImm(3)); + EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ShadowRegI32).addReg( + AddressRegI32)); + EmitInstruction(Out, MCInstBuilder(X86::SHR32ri) + .addReg(ShadowRegI32) + .addReg(ShadowRegI32) + .addImm(3)); { MCInst Inst; Inst.setOpcode(X86::MOV8rm); - Inst.addOperand(MCOperand::CreateReg(X86::CL)); + Inst.addOperand(MCOperand::CreateReg(ShadowRegI8)); const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx); std::unique_ptr Op( - X86Operand::CreateMem(0, Disp, X86::ECX, 0, 1, SMLoc(), SMLoc())); + X86Operand::CreateMem(0, Disp, ShadowRegI32, 0, 1, SMLoc(), SMLoc())); Op->addMemOperands(Inst, 5); EmitInstruction(Out, Inst); } - EmitInstruction(Out, - MCInstBuilder(X86::TEST8rr).addReg(X86::CL).addReg(X86::CL)); + EmitInstruction( + Out, MCInstBuilder(X86::TEST8rr).addReg(ShadowRegI8).addReg(ShadowRegI8)); MCSymbol *DoneSym = Ctx.CreateTempSymbol(); const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx); EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr)); - EmitInstruction( - Out, MCInstBuilder(X86::MOV32rr).addReg(X86::EDX).addReg(X86::EAX)); - EmitInstruction(Out, MCInstBuilder(X86::AND32ri).addReg(X86::EDX) - .addReg(X86::EDX).addImm(7)); + EmitInstruction(Out, MCInstBuilder(X86::MOV32rr) + .addReg(ExpectedShadowValueRegI32) + .addReg(AddressRegI32)); + EmitInstruction(Out, MCInstBuilder(X86::AND32ri) + .addReg(ExpectedShadowValueRegI32) + .addReg(ExpectedShadowValueRegI32) + .addImm(7)); - switch (AccessSize) { + switch (AsanCtx.AccessSize) { case 1: break; case 2: { MCInst Inst; Inst.setOpcode(X86::LEA32r); - Inst.addOperand(MCOperand::CreateReg(X86::EDX)); + Inst.addOperand(MCOperand::CreateReg(ExpectedShadowValueRegI32)); const MCExpr *Disp = MCConstantExpr::Create(1, Ctx); - std::unique_ptr Op( - X86Operand::CreateMem(0, Disp, X86::EDX, 0, 1, SMLoc(), SMLoc())); + std::unique_ptr Op(X86Operand::CreateMem( + 0, Disp, ExpectedShadowValueRegI32, 0, 1, SMLoc(), SMLoc())); Op->addMemOperands(Inst, 5); EmitInstruction(Out, Inst); break; } case 4: - EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8).addReg(X86::EDX) - .addReg(X86::EDX).addImm(3)); + EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8) + .addReg(ExpectedShadowValueRegI32) + .addReg(ExpectedShadowValueRegI32) + .addImm(3)); break; default: assert(false && "Incorrect access size"); @@ -324,54 +444,53 @@ } EmitInstruction( - Out, MCInstBuilder(X86::MOVSX32rr8).addReg(X86::ECX).addReg(X86::CL)); - EmitInstruction( - Out, MCInstBuilder(X86::CMP32rr).addReg(X86::EDX).addReg(X86::ECX)); + Out, + MCInstBuilder(X86::MOVSX32rr8).addReg(ShadowRegI32).addReg(ShadowRegI8)); + EmitInstruction(Out, MCInstBuilder(X86::CMP32rr) + .addReg(ExpectedShadowValueRegI32) + .addReg(ShadowRegI32)); EmitInstruction(Out, MCInstBuilder(X86::JL_4).addExpr(DoneExpr)); - EmitCallAsanReport(Ctx, Out, AccessSize, IsWrite, X86::EAX); + EmitCallAsanReport(Ctx, Out, AsanCtx); EmitLabel(Out, DoneSym); - - EmitInstruction(Out, MCInstBuilder(X86::POPF32)); - EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::EDX)); - EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::ECX)); - EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::EAX)); } -void X86AddressSanitizer32::InstrumentMemOperandLargeImpl( - X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, +void X86AddressSanitizer32::InstrumentMemOperandLarge( + X86Operand &Op, const AsanContext &AsanCtx, MCContext &Ctx, MCStreamer &Out) { - EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::EAX)); - EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::ECX)); - EmitInstruction(Out, MCInstBuilder(X86::PUSHF32)); + unsigned AddressRegI32 = AsanCtx.addressReg(MVT::i32); + unsigned ShadowRegI32 = AsanCtx.shadowReg(MVT::i32); { MCInst Inst; Inst.setOpcode(X86::LEA32r); - Inst.addOperand(MCOperand::CreateReg(X86::EAX)); + Inst.addOperand(MCOperand::CreateReg(AddressRegI32)); Op.addMemOperands(Inst, 5); EmitInstruction(Out, Inst); } - EmitInstruction( - Out, MCInstBuilder(X86::MOV32rr).addReg(X86::ECX).addReg(X86::EAX)); - EmitInstruction(Out, MCInstBuilder(X86::SHR32ri).addReg(X86::ECX) - .addReg(X86::ECX).addImm(3)); + + EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ShadowRegI32).addReg( + AddressRegI32)); + EmitInstruction(Out, MCInstBuilder(X86::SHR32ri) + .addReg(ShadowRegI32) + .addReg(ShadowRegI32) + .addImm(3)); { MCInst Inst; - switch (AccessSize) { - case 8: - Inst.setOpcode(X86::CMP8mi); - break; - case 16: - Inst.setOpcode(X86::CMP16mi); - break; - default: - assert(false && "Incorrect access size"); - break; + switch (AsanCtx.AccessSize) { + case 8: + Inst.setOpcode(X86::CMP8mi); + break; + case 16: + Inst.setOpcode(X86::CMP16mi); + break; + default: + assert(false && "Incorrect access size"); + break; } const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx); std::unique_ptr Op( - X86Operand::CreateMem(0, Disp, X86::ECX, 0, 1, SMLoc(), SMLoc())); + X86Operand::CreateMem(0, Disp, ShadowRegI32, 0, 1, SMLoc(), SMLoc())); Op->addMemOperands(Inst, 5); Inst.addOperand(MCOperand::CreateImm(0)); EmitInstruction(Out, Inst); @@ -380,17 +499,14 @@ const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx); EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr)); - EmitCallAsanReport(Ctx, Out, AccessSize, IsWrite, X86::EAX); + EmitCallAsanReport(Ctx, Out, AsanCtx); EmitLabel(Out, DoneSym); - - EmitInstruction(Out, MCInstBuilder(X86::POPF32)); - EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::ECX)); - EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::EAX)); } -void X86AddressSanitizer32::InstrumentMOVSImpl( - unsigned AccessSize, MCContext &Ctx, MCStreamer &Out) { - EmitInstruction(Out, MCInstBuilder(X86::PUSHF32)); +void X86AddressSanitizer32::InstrumentMOVSImpl(unsigned AccessSize, + MCContext &Ctx, + MCStreamer &Out) { + StoreFlags(Out); // No need to test when ECX is equals to zero. MCSymbol *DoneSym = Ctx.CreateTempSymbol(); @@ -404,7 +520,7 @@ X86::ECX /* CntReg */, AccessSize, Ctx, Out); EmitLabel(Out, DoneSym); - EmitInstruction(Out, MCInstBuilder(X86::POPF32)); + RestoreFlags(Out); } class X86AddressSanitizer64 : public X86AddressSanitizer { @@ -415,12 +531,52 @@ : X86AddressSanitizer(STI) {} virtual ~X86AddressSanitizer64() {} - virtual void InstrumentMemOperandSmallImpl( - X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, - MCStreamer &Out) override; - virtual void InstrumentMemOperandLargeImpl( - X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, - MCStreamer &Out) override; + virtual void StoreFlags(MCStreamer &Out) override { + EmitInstruction(Out, MCInstBuilder(X86::PUSHF64)); + } + + virtual void RestoreFlags(MCStreamer &Out) override { + EmitInstruction(Out, MCInstBuilder(X86::POPF64)); + } + + virtual void InstrumentMemOperandPrologue(const AsanContext &AsanCtx, + MCContext &Ctx, + MCStreamer &Out) override { + EmitAdjustRSP(Ctx, Out, -128); + EmitInstruction( + Out, MCInstBuilder(X86::PUSH64r).addReg(AsanCtx.shadowReg(MVT::i64))); + EmitInstruction( + Out, MCInstBuilder(X86::PUSH64r).addReg(AsanCtx.addressReg(MVT::i64))); + if (IsSmallMemAccess(AsanCtx.AccessSize)) { + EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg( + AsanCtx.expectedShadowValueReg(MVT::i64))); + } + StoreFlags(Out); + } + + virtual void InstrumentMemOperandEpilogue(const AsanContext &AsanCtx, + MCContext &Ctx, + MCStreamer &Out) override { + RestoreFlags(Out); + if (IsSmallMemAccess(AsanCtx.AccessSize)) { + EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg( + AsanCtx.expectedShadowValueReg(MVT::i64))); + } + EmitInstruction( + Out, MCInstBuilder(X86::POP64r).addReg(AsanCtx.addressReg(MVT::i64))); + EmitInstruction( + Out, MCInstBuilder(X86::POP64r).addReg(AsanCtx.shadowReg(MVT::i64))); + EmitAdjustRSP(Ctx, Out, 128); + } + + virtual void InstrumentMemOperandSmall(X86Operand &Op, + const AsanContext &AsanCtx, + MCContext &Ctx, + MCStreamer &Out) override; + virtual void InstrumentMemOperandLarge(X86Operand &Op, + const AsanContext &AsanCtx, + MCContext &Ctx, + MCStreamer &Out) override; virtual void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx, MCStreamer &Out) override; @@ -437,15 +593,21 @@ EmitInstruction(Out, Inst); } - void EmitCallAsanReport(MCContext &Ctx, MCStreamer &Out, unsigned AccessSize, - bool IsWrite) { + void EmitCallAsanReport(MCContext &Ctx, MCStreamer &Out, + const AsanContext &AsanCtx) { EmitInstruction(Out, MCInstBuilder(X86::CLD)); EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS)); - EmitInstruction(Out, MCInstBuilder(X86::AND64ri8).addReg(X86::RSP) - .addReg(X86::RSP).addImm(-16)); + EmitInstruction(Out, MCInstBuilder(X86::AND64ri8) + .addReg(X86::RSP) + .addReg(X86::RSP) + .addImm(-16)); - const std::string &Fn = FuncName(AccessSize, IsWrite); + if (AsanCtx.AddressReg != X86::RDI) { + EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(X86::RDI).addReg( + AsanCtx.addressReg(MVT::i64))); + } + const std::string &Fn = FuncName(AsanCtx.AccessSize, AsanCtx.IsWrite); MCSymbol *FnSym = Ctx.GetOrCreateSymbol(StringRef(Fn)); const MCSymbolRefExpr *FnExpr = MCSymbolRefExpr::Create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx); @@ -453,65 +615,75 @@ } }; -void X86AddressSanitizer64::InstrumentMemOperandSmallImpl( - X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, +void X86AddressSanitizer64::InstrumentMemOperandSmall( + X86Operand &Op, const AsanContext &AsanCtx, MCContext &Ctx, MCStreamer &Out) { - EmitAdjustRSP(Ctx, Out, -128); - EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RAX)); - EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RCX)); - EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RDI)); - EmitInstruction(Out, MCInstBuilder(X86::PUSHF64)); + unsigned AddressRegI64 = AsanCtx.addressReg(MVT::i64); + unsigned AddressRegI32 = AsanCtx.addressReg(MVT::i32); + unsigned ShadowRegI64 = AsanCtx.shadowReg(MVT::i64); + unsigned ShadowRegI32 = AsanCtx.shadowReg(MVT::i32); + unsigned ShadowRegI8 = AsanCtx.shadowReg(MVT::i8); + + unsigned ExpectedShadowValueRegI32 = AsanCtx.expectedShadowValueReg(MVT::i32); + { MCInst Inst; Inst.setOpcode(X86::LEA64r); - Inst.addOperand(MCOperand::CreateReg(X86::RDI)); + Inst.addOperand(MCOperand::CreateReg(AddressRegI64)); Op.addMemOperands(Inst, 5); EmitInstruction(Out, Inst); } - EmitInstruction( - Out, MCInstBuilder(X86::MOV64rr).addReg(X86::RAX).addReg(X86::RDI)); - EmitInstruction(Out, MCInstBuilder(X86::SHR64ri).addReg(X86::RAX) - .addReg(X86::RAX).addImm(3)); + EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(ShadowRegI64).addReg( + AddressRegI64)); + EmitInstruction(Out, MCInstBuilder(X86::SHR64ri) + .addReg(ShadowRegI64) + .addReg(ShadowRegI64) + .addImm(3)); { MCInst Inst; Inst.setOpcode(X86::MOV8rm); - Inst.addOperand(MCOperand::CreateReg(X86::AL)); + Inst.addOperand(MCOperand::CreateReg(ShadowRegI8)); const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx); std::unique_ptr Op( - X86Operand::CreateMem(0, Disp, X86::RAX, 0, 1, SMLoc(), SMLoc())); + X86Operand::CreateMem(0, Disp, ShadowRegI64, 0, 1, SMLoc(), SMLoc())); Op->addMemOperands(Inst, 5); EmitInstruction(Out, Inst); } - EmitInstruction(Out, - MCInstBuilder(X86::TEST8rr).addReg(X86::AL).addReg(X86::AL)); + EmitInstruction( + Out, MCInstBuilder(X86::TEST8rr).addReg(ShadowRegI8).addReg(ShadowRegI8)); MCSymbol *DoneSym = Ctx.CreateTempSymbol(); const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx); EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr)); - EmitInstruction( - Out, MCInstBuilder(X86::MOV32rr).addReg(X86::ECX).addReg(X86::EDI)); - EmitInstruction(Out, MCInstBuilder(X86::AND32ri).addReg(X86::ECX) - .addReg(X86::ECX).addImm(7)); + EmitInstruction(Out, MCInstBuilder(X86::MOV32rr) + .addReg(ExpectedShadowValueRegI32) + .addReg(AddressRegI32)); + EmitInstruction(Out, MCInstBuilder(X86::AND32ri) + .addReg(ExpectedShadowValueRegI32) + .addReg(ExpectedShadowValueRegI32) + .addImm(7)); - switch (AccessSize) { + switch (AsanCtx.AccessSize) { case 1: break; case 2: { MCInst Inst; Inst.setOpcode(X86::LEA32r); - Inst.addOperand(MCOperand::CreateReg(X86::ECX)); + Inst.addOperand(MCOperand::CreateReg(ExpectedShadowValueRegI32)); const MCExpr *Disp = MCConstantExpr::Create(1, Ctx); - std::unique_ptr Op( - X86Operand::CreateMem(0, Disp, X86::ECX, 0, 1, SMLoc(), SMLoc())); + std::unique_ptr Op(X86Operand::CreateMem( + 0, Disp, ExpectedShadowValueRegI32, 0, 1, SMLoc(), SMLoc())); Op->addMemOperands(Inst, 5); EmitInstruction(Out, Inst); break; } case 4: - EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8).addReg(X86::ECX) - .addReg(X86::ECX).addImm(3)); + EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8) + .addReg(ExpectedShadowValueRegI32) + .addReg(ExpectedShadowValueRegI32) + .addImm(3)); break; default: assert(false && "Incorrect access size"); @@ -519,40 +691,39 @@ } EmitInstruction( - Out, MCInstBuilder(X86::MOVSX32rr8).addReg(X86::EAX).addReg(X86::AL)); - EmitInstruction( - Out, MCInstBuilder(X86::CMP32rr).addReg(X86::ECX).addReg(X86::EAX)); + Out, + MCInstBuilder(X86::MOVSX32rr8).addReg(ShadowRegI32).addReg(ShadowRegI8)); + EmitInstruction(Out, MCInstBuilder(X86::CMP32rr) + .addReg(ExpectedShadowValueRegI32) + .addReg(ShadowRegI32)); EmitInstruction(Out, MCInstBuilder(X86::JL_4).addExpr(DoneExpr)); - EmitCallAsanReport(Ctx, Out, AccessSize, IsWrite); + EmitCallAsanReport(Ctx, Out, AsanCtx); EmitLabel(Out, DoneSym); - - EmitInstruction(Out, MCInstBuilder(X86::POPF64)); - EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(X86::RDI)); - EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(X86::RCX)); - EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(X86::RAX)); - EmitAdjustRSP(Ctx, Out, 128); } -void X86AddressSanitizer64::InstrumentMemOperandLargeImpl( - X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, +void X86AddressSanitizer64::InstrumentMemOperandLarge( + X86Operand &Op, const AsanContext &AsanCtx, MCContext &Ctx, MCStreamer &Out) { - EmitAdjustRSP(Ctx, Out, -128); - EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RAX)); - EmitInstruction(Out, MCInstBuilder(X86::PUSHF64)); + unsigned AddressRegI64 = AsanCtx.addressReg(MVT::i64); + unsigned ShadowRegI64 = AsanCtx.shadowReg(MVT::i64); { MCInst Inst; Inst.setOpcode(X86::LEA64r); - Inst.addOperand(MCOperand::CreateReg(X86::RAX)); + Inst.addOperand(MCOperand::CreateReg(AddressRegI64)); Op.addMemOperands(Inst, 5); EmitInstruction(Out, Inst); } - EmitInstruction(Out, MCInstBuilder(X86::SHR64ri).addReg(X86::RAX) - .addReg(X86::RAX).addImm(3)); + EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(ShadowRegI64).addReg( + AddressRegI64)); + EmitInstruction(Out, MCInstBuilder(X86::SHR64ri) + .addReg(ShadowRegI64) + .addReg(ShadowRegI64) + .addImm(3)); { MCInst Inst; - switch (AccessSize) { + switch (AsanCtx.AccessSize) { case 8: Inst.setOpcode(X86::CMP8mi); break; @@ -565,7 +736,7 @@ } const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx); std::unique_ptr Op( - X86Operand::CreateMem(0, Disp, X86::RAX, 0, 1, SMLoc(), SMLoc())); + X86Operand::CreateMem(0, Disp, ShadowRegI64, 0, 1, SMLoc(), SMLoc())); Op->addMemOperands(Inst, 5); Inst.addOperand(MCOperand::CreateImm(0)); EmitInstruction(Out, Inst); @@ -575,17 +746,14 @@ const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx); EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr)); - EmitCallAsanReport(Ctx, Out, AccessSize, IsWrite); + EmitCallAsanReport(Ctx, Out, AsanCtx); EmitLabel(Out, DoneSym); - - EmitInstruction(Out, MCInstBuilder(X86::POPF64)); - EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(X86::RAX)); - EmitAdjustRSP(Ctx, Out, 128); } -void X86AddressSanitizer64::InstrumentMOVSImpl( - unsigned AccessSize, MCContext &Ctx, MCStreamer &Out) { - EmitInstruction(Out, MCInstBuilder(X86::PUSHF64)); +void X86AddressSanitizer64::InstrumentMOVSImpl(unsigned AccessSize, + MCContext &Ctx, + MCStreamer &Out) { + StoreFlags(Out); // No need to test when RCX is equals to zero. MCSymbol *DoneSym = Ctx.CreateTempSymbol(); @@ -599,7 +767,7 @@ X86::RCX /* CntReg */, AccessSize, Ctx, Out); EmitLabel(Out, DoneSym); - EmitInstruction(Out, MCInstBuilder(X86::POPF64)); + RestoreFlags(Out); } } // End anonymous namespace Index: lib/Target/X86/X86ISelLowering.cpp =================================================================== --- lib/Target/X86/X86ISelLowering.cpp +++ lib/Target/X86/X86ISelLowering.cpp @@ -1016,10 +1016,8 @@ // scalars) and extend in-register to a legal 128-bit vector type. For sext // loads these must work with a single scalar load. setLoadExtAction(ISD::SEXTLOAD, MVT::v4i8, Custom); - if (Subtarget->is64Bit()) { - setLoadExtAction(ISD::SEXTLOAD, MVT::v4i16, Custom); - setLoadExtAction(ISD::SEXTLOAD, MVT::v8i8, Custom); - } + setLoadExtAction(ISD::SEXTLOAD, MVT::v4i16, Custom); + setLoadExtAction(ISD::SEXTLOAD, MVT::v8i8, Custom); setLoadExtAction(ISD::EXTLOAD, MVT::v2i8, Custom); setLoadExtAction(ISD::EXTLOAD, MVT::v2i16, Custom); setLoadExtAction(ISD::EXTLOAD, MVT::v2i32, Custom); @@ -19787,7 +19785,6 @@ EVT VT = InVec.getValueType(); - bool HasShuffleIntoBitcast = false; if (InVec.getOpcode() == ISD::BITCAST) { // Don't duplicate a load with other uses. if (!InVec.hasOneUse()) @@ -19796,7 +19793,6 @@ if (BCVT.getVectorNumElements() != VT.getVectorNumElements()) return SDValue(); InVec = InVec.getOperand(0); - HasShuffleIntoBitcast = true; } if (!isTargetShuffle(InVec.getOpcode())) @@ -19839,17 +19835,16 @@ if (!LN0 ||!LN0->hasNUsesOfValue(AllowedUses, 0) || LN0->isVolatile()) return SDValue(); - if (HasShuffleIntoBitcast) { - // If there's a bitcast before the shuffle, check if the load type and - // alignment is valid. - unsigned Align = LN0->getAlignment(); - const TargetLowering &TLI = DAG.getTargetLoweringInfo(); - unsigned NewAlign = TLI.getDataLayout()-> - getABITypeAlignment(VT.getTypeForEVT(*DAG.getContext())); + EVT EltVT = N->getValueType(0); + // If there's a bitcast before the shuffle, check if the load type and + // alignment is valid. + unsigned Align = LN0->getAlignment(); + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + unsigned NewAlign = TLI.getDataLayout()->getABITypeAlignment( + EltVT.getTypeForEVT(*DAG.getContext())); - if (NewAlign > Align || !TLI.isOperationLegalOrCustom(ISD::LOAD, VT)) - return SDValue(); - } + if (NewAlign > Align || !TLI.isOperationLegalOrCustom(ISD::LOAD, EltVT)) + return SDValue(); // All checks match so transform back to vector_shuffle so that DAG combiner // can finish the job Index: test/CodeGen/X86/extractelement-load.ll =================================================================== --- test/CodeGen/X86/extractelement-load.ll +++ test/CodeGen/X86/extractelement-load.ll @@ -1,6 +1,8 @@ ; RUN: llc < %s -march=x86 -mattr=+sse2 -mcpu=yonah | FileCheck %s ; RUN: llc < %s -march=x86-64 -mattr=+sse2 -mcpu=core2 | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + define i32 @t(<2 x i64>* %val) nounwind { ; CHECK-LABEL: t: ; CHECK-NOT: movd @@ -23,3 +25,22 @@ %y = extractelement <8 x i32> %Shuff68, i32 0 ret i32 %y } + +; This case could easily end up inf-looping in the DAG combiner due to an +; low alignment load of the vector which prevents us from reliably forming a +; narrow load. +; FIXME: It would be nice to detect whether the target has fast and legal +; unaligned loads and use them here. +define void @t3() { +; CHECK-LABEL: t3: +; +; This movs the entire vector, shuffling the high double down. If we fixed the +; FIXME above it would just move the high double directly. +; CHECK: movhpd %xmm + +bb: + %tmp13 = load <2 x double>* undef, align 1 + %.sroa.3.24.vec.extract = extractelement <2 x double> %tmp13, i32 1 + store double %.sroa.3.24.vec.extract, double* undef, align 8 + unreachable +} Index: test/CodeGen/X86/vec_sext.ll =================================================================== --- test/CodeGen/X86/vec_sext.ll +++ test/CodeGen/X86/vec_sext.ll @@ -1,5 +1,5 @@ -; RUN: llc < %s -march=x86-64 -; PR 9267 +; RUN: llc < %s -march=x86-64 -mattr=+avx | FileCheck %s +; RUN: llc < %s -march=x86 -mattr=+avx | FileCheck %s define<4 x i32> @func_16_32() { %F = load <4 x i16>* undef @@ -67,3 +67,14 @@ ret <4 x i64> %G } +define <4 x i32> @sextload(<4 x i16>* %ptr) { +; From PR20767 - make sure that we correctly use SSE4.1 to do sign extension +; loads for both 32-bit and 64-bit x86 targets. +; CHECK-LABEL: sextload: +; CHECK: vpmovsxwd {{.*}}, %xmm0 +; CHECK-NEXT: ret +entry: + %l = load<4 x i16>* %ptr + %m = sext<4 x i16> %l to <4 x i32> + ret <4 x i32> %m +} Index: test/CodeGen/X86/vector-shuffle-128-v16.ll =================================================================== --- test/CodeGen/X86/vector-shuffle-128-v16.ll +++ test/CodeGen/X86/vector-shuffle-128-v16.ll @@ -1,11 +1,6 @@ ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mcpu=x86-64 -x86-experimental-vector-shuffle-lowering | FileCheck %s --check-prefix=ALL --check-prefix=SSE2 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mcpu=x86-64 -mattr=+ssse3 -x86-experimental-vector-shuffle-lowering | FileCheck %s --check-prefix=ALL --check-prefix=SSSE3 -; XFAIL: * -; Only @stress_test0 is expected to fail, but XFAIL is not that selective. I -; expect this to be unxfailed soon enough that we won't regress the other tests -; in the interim. - target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-unknown" Index: test/Instrumentation/AddressSanitizer/X86/asm_mov.ll =================================================================== --- test/Instrumentation/AddressSanitizer/X86/asm_mov.ll +++ test/Instrumentation/AddressSanitizer/X86/asm_mov.ll @@ -6,8 +6,8 @@ ; CHECK-LABEL: mov1b ; CHECK: leaq -128(%rsp), %rsp ; CHECK-NEXT: pushq %rax -; CHECK-NEXT: pushq %rcx ; CHECK-NEXT: pushq %rdi +; CHECK-NEXT: pushq %rcx ; CHECK-NEXT: pushfq ; CHECK-NEXT: leaq {{.*}}, %rdi ; CHECK-NEXT: movq %rdi, %rax @@ -26,8 +26,8 @@ ; CHECK-NEXT: callq __asan_report_load1@PLT ; CHECK-NEXT: [[A]]: ; CHECK-NEXT: popfq -; CHECK-NEXT: popq %rdi ; CHECK-NEXT: popq %rcx +; CHECK-NEXT: popq %rdi ; CHECK-NEXT: popq %rax ; CHECK-NEXT: leaq 128(%rsp), %rsp @@ -81,8 +81,10 @@ ; CHECK-LABEL: mov8b ; CHECK: leaq -128(%rsp), %rsp ; CHECK-NEXT: pushq %rax +; CHECK-NEXT: pushq %rdi ; CHECK-NEXT: pushfq -; CHECK-NEXT: leaq {{.*}}, %rax +; CHECK-NEXT: leaq {{.*}}, %rdi +; CHECK-NEXT: movq %rdi, %rax ; CHECK-NEXT: shrq $3, %rax ; CHECK-NEXT: cmpb $0, 2147450880(%rax) ; CHECK-NEXT: je [[A:.*]] @@ -92,13 +94,16 @@ ; CHECK-NEXT: callq __asan_report_load8@PLT ; CHECK-NEXT: [[A]]: ; CHECK-NEXT: popfq +; CHECK-NEXT: popq %rdi ; CHECK-NEXT: popq %rax ; CHECK-NEXT: leaq 128(%rsp), %rsp ; CHECK: leaq -128(%rsp), %rsp ; CHECK-NEXT: pushq %rax +; CHECK-NEXT: pushq %rdi ; CHECK-NEXT: pushfq -; CHECK-NEXT: leaq {{.*}}, %rax +; CHECK-NEXT: leaq {{.*}}, %rdi +; CHECK-NEXT: movq %rdi, %rax ; CHECK-NEXT: shrq $3, %rax ; CHECK-NEXT: cmpb $0, 2147450880(%rax) ; CHECK-NEXT: je [[A:.*]] @@ -108,6 +113,7 @@ ; CHECK-NEXT: callq __asan_report_store8@PLT ; CHECK-NEXT: [[A]]: ; CHECK-NEXT: popfq +; CHECK-NEXT: popq %rdi ; CHECK-NEXT: popq %rax ; CHECK-NEXT: leaq 128(%rsp), %rsp Index: test/Instrumentation/AddressSanitizer/X86/asm_rep_movs.ll =================================================================== --- test/Instrumentation/AddressSanitizer/X86/asm_rep_movs.ll +++ test/Instrumentation/AddressSanitizer/X86/asm_rep_movs.ll @@ -8,17 +8,33 @@ ; CHECK-NEXT: testq %rcx, %rcx ; CHECK-NEXT: je [[B:.*]] -; CHECK: leaq (%rsi), {{.*}} -; CHECK: callq __asan_report_load1@PLT - -; CHECK: leaq -1(%rsi,%rcx), {{.*}} -; CHECK: callq __asan_report_load1@PLT - -; CHECK: leaq (%rdi), {{.*}} -; CHECK: callq __asan_report_store1@PLT - -; CHECK: leaq -1(%rdi,%rcx), {{.*}} -; CHECK: callq __asan_report_store1@PLT +; CHECK: leaq -128(%rsp), %rsp +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: pushq %rdx +; CHECK-NEXT: pushq %rbx +; CHECK-NEXT: pushfq + +; CHECK: leaq (%rsi), %rdx +; CHECK: movq %rdx, %rdi +; CHECK-NEXT: callq __asan_report_load1@PLT + +; CHECK: leaq -1(%rsi,%rcx), %rdx +; CHECK: movq %rdx, %rdi +; CHECK-NEXT: callq __asan_report_load1@PLT + +; CHECK: leaq (%rdi), %rdx +; CHECK: movq %rdx, %rdi +; CHECK-NEXT: callq __asan_report_store1@PLT + +; CHECK: leaq -1(%rdi,%rcx), %rdx +; CHECK: movq %rdx, %rdi +; CHECK-NEXT: callq __asan_report_store1@PLT + +; CHECK: popfq +; CHECK-NEXT: popq %rbx +; CHECK-NEXT: popq %rdx +; CHECK-NEXT: popq %rax +; CHECK-NEXT: leaq 128(%rsp), %rsp ; CHECK: [[B]]: ; CHECK-NEXT: popfq @@ -38,17 +54,21 @@ ; CHECK-NEXT: testq %rcx, %rcx ; CHECK-NEXT: je [[Q:.*]] -; CHECK: leaq (%rsi), {{.*}} -; CHECK: callq __asan_report_load8@PLT +; CHECK: leaq (%rsi), %rdx +; CHECK: movq %rdx, %rdi +; CHECK-NEXT: callq __asan_report_load8@PLT -; CHECK: leaq -1(%rsi,%rcx,8), {{.*}} -; CHECK: callq __asan_report_load8@PLT +; CHECK: leaq -1(%rsi,%rcx,8), %rdx +; CHECK: movq %rdx, %rdi +; CHECK-NEXT: callq __asan_report_load8@PLT -; CHECK: leaq (%rdi), {{.*}} -; CHECK: callq __asan_report_store8@PLT +; CHECK: leaq (%rdi), %rdx +; CHECK: movq %rdx, %rdi +; CHECK-NEXT: callq __asan_report_store8@PLT -; CHECK: leaq -1(%rdi,%rcx,8), {{.*}} -; CHECK: callq __asan_report_store8@PLT +; CHECK: leaq -1(%rdi,%rcx,8), %rdx +; CHECK: movq %rdx, %rdi +; CHECK-NEXT: callq __asan_report_store8@PLT ; CHECK: [[Q]]: ; CHECK-NEXT: popfq