Index: clang/docs/SanitizerCoverage.rst =================================================================== --- clang/docs/SanitizerCoverage.rst +++ clang/docs/SanitizerCoverage.rst @@ -293,6 +293,9 @@ void __sanitizer_cov_trace_cmp2(uint16_t Arg1, uint16_t Arg2); void __sanitizer_cov_trace_cmp4(uint32_t Arg1, uint32_t Arg2); void __sanitizer_cov_trace_cmp8(uint64_t Arg1, uint64_t Arg2); + void __sanitizer_cov_trace_cmp_fp2(half Arg1, half Arg2); + void __sanitizer_cov_trace_cmp_fp4(float Arg1, float Arg2); + void __sanitizer_cov_trace_cmp_fp8(double Arg1, double Arg2); // Called before a comparison instruction if exactly one of the arguments is constant. // Arg1 and Arg2 are arguments of the comparison, Arg1 is a compile-time constant. @@ -301,6 +304,9 @@ void __sanitizer_cov_trace_const_cmp2(uint16_t Arg1, uint16_t Arg2); void __sanitizer_cov_trace_const_cmp4(uint32_t Arg1, uint32_t Arg2); void __sanitizer_cov_trace_const_cmp8(uint64_t Arg1, uint64_t Arg2); + void __sanitizer_cov_trace_const_cmp_fp2(half Arg1, half Arg2); + void __sanitizer_cov_trace_const_cmp_fp4(float Arg1, float Arg2); + void __sanitizer_cov_trace_const_cmp_fp8(double Arg1, double Arg2); // Called before a switch statement. // Val is the switch operand. Index: compiler-rt/lib/dfsan/done_abilist.txt =================================================================== --- compiler-rt/lib/dfsan/done_abilist.txt +++ compiler-rt/lib/dfsan/done_abilist.txt @@ -401,6 +401,12 @@ fun:__sanitizer_cov_trace_cmp4=uninstrumented fun:__sanitizer_cov_trace_cmp8=custom fun:__sanitizer_cov_trace_cmp8=uninstrumented +fun:__sanitizer_cov_trace_cmp_fp2=custom +fun:__sanitizer_cov_trace_cmp_fp2=uninstrumented +fun:__sanitizer_cov_trace_cmp_fp4=custom +fun:__sanitizer_cov_trace_cmp_fp4=uninstrumented +fun:__sanitizer_cov_trace_cmp_fp8=custom +fun:__sanitizer_cov_trace_cmp_fp8=uninstrumented fun:__sanitizer_cov_trace_const_cmp1=custom fun:__sanitizer_cov_trace_const_cmp1=uninstrumented fun:__sanitizer_cov_trace_const_cmp2=custom @@ -409,6 +415,12 @@ fun:__sanitizer_cov_trace_const_cmp4=uninstrumented fun:__sanitizer_cov_trace_const_cmp8=custom fun:__sanitizer_cov_trace_const_cmp8=uninstrumented +fun:__sanitizer_cov_trace_const_cmp_fp2=custom +fun:__sanitizer_cov_trace_const_cmp_fp2=uninstrumented +fun:__sanitizer_cov_trace_const_cmp_fp4=custom +fun:__sanitizer_cov_trace_const_cmp_fp4=uninstrumented +fun:__sanitizer_cov_trace_const_cmp_fp8=custom +fun:__sanitizer_cov_trace_const_cmp_fp8=uninstrumented # Similar for __sanitizer_cov_trace_switch fun:__sanitizer_cov_trace_switch=custom fun:__sanitizer_cov_trace_switch=uninstrumented Index: compiler-rt/lib/sanitizer_common/sanitizer_coverage_fuchsia.cpp =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_coverage_fuchsia.cpp +++ compiler-rt/lib/sanitizer_common/sanitizer_coverage_fuchsia.cpp @@ -239,10 +239,16 @@ SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp2, void) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp4, void) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp8, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp_fp2, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp_fp4, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp_fp8, void) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_const_cmp1, void) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_const_cmp2, void) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_const_cmp4, void) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_const_cmp8, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_const_cmp_fp2, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_const_cmp_fp4, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_const_cmp_fp8, void) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_switch, void) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_div4, void) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_div8, void) {} Index: compiler-rt/lib/sanitizer_common/sanitizer_coverage_interface.inc =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_coverage_interface.inc +++ compiler-rt/lib/sanitizer_common/sanitizer_coverage_interface.inc @@ -17,10 +17,16 @@ INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp2) INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp4) INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp8) +INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp_fp2) +INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp_fp4) +INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp_fp8) INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_const_cmp1) INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_const_cmp2) INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_const_cmp4) INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_const_cmp8) +INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_const_cmp_fp2) +INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_const_cmp_fp4) +INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_const_cmp_fp8) INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_div4) INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_div8) INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_gep) Index: compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cpp =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cpp +++ compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cpp @@ -247,10 +247,16 @@ SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp2, void) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp4, void) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp8, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp_fp2, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp_fp4, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp_fp8, void) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_const_cmp1, void) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_const_cmp2, void) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_const_cmp4, void) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_const_cmp8, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_const_cmp_fp2, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_const_cmp_fp4, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_const_cmp_fp8, void) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_switch, void) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_div4, void) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_div8, void) {} Index: llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -52,10 +52,16 @@ const char SanCovTraceCmp2[] = "__sanitizer_cov_trace_cmp2"; const char SanCovTraceCmp4[] = "__sanitizer_cov_trace_cmp4"; const char SanCovTraceCmp8[] = "__sanitizer_cov_trace_cmp8"; +const char SanCovTraceCmpF2[] = "__sanitizer_cov_trace_cmp_fp2"; +const char SanCovTraceCmpF4[] = "__sanitizer_cov_trace_cmp_fp4"; +const char SanCovTraceCmpF8[] = "__sanitizer_cov_trace_cmp_fp8"; const char SanCovTraceConstCmp1[] = "__sanitizer_cov_trace_const_cmp1"; const char SanCovTraceConstCmp2[] = "__sanitizer_cov_trace_const_cmp2"; const char SanCovTraceConstCmp4[] = "__sanitizer_cov_trace_const_cmp4"; const char SanCovTraceConstCmp8[] = "__sanitizer_cov_trace_const_cmp8"; +const char SanCovTraceConstCmpF2[] = "__sanitizer_cov_trace_const_cmp_fp2"; +const char SanCovTraceConstCmpF4[] = "__sanitizer_cov_trace_const_cmp_fp4"; +const char SanCovTraceConstCmpF8[] = "__sanitizer_cov_trace_const_cmp_fp8"; const char SanCovLoad1[] = "__sanitizer_cov_load1"; const char SanCovLoad2[] = "__sanitizer_cov_load2"; const char SanCovLoad4[] = "__sanitizer_cov_load4"; @@ -257,8 +263,8 @@ std::string getSectionEnd(const std::string &Section) const; FunctionCallee SanCovTracePCIndir; FunctionCallee SanCovTracePC, SanCovTracePCGuard; - std::array SanCovTraceCmpFunction; - std::array SanCovTraceConstCmpFunction; + std::array SanCovTraceCmpFunction; + std::array SanCovTraceConstCmpFunction; std::array SanCovLoadFunction; std::array SanCovStoreFunction; std::array SanCovTraceDivFunction; @@ -267,7 +273,8 @@ GlobalVariable *SanCovLowestStack; Type *Int128PtrTy, *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy, *Int16PtrTy, *Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, - *Int1PtrTy; + *Int1PtrTy, + *Fp16Ty, *Fp16PtrTy, *Fp32Ty, *Fp32PtrTy, *Fp64Ty, *Fp64PtrTy; Module *CurModule; std::string CurModuleUniqueId; Triple TargetTriple; @@ -443,11 +450,17 @@ Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty()); Int8PtrTy = PointerType::getUnqual(IRB.getInt8Ty()); Int1PtrTy = PointerType::getUnqual(IRB.getInt1Ty()); + Fp16PtrTy = PointerType::getUnqual(IRB.getHalfTy()); + Fp32PtrTy = PointerType::getUnqual(IRB.getFloatTy()); + Fp64PtrTy = PointerType::getUnqual(IRB.getDoubleTy()); Int64Ty = IRB.getInt64Ty(); Int32Ty = IRB.getInt32Ty(); Int16Ty = IRB.getInt16Ty(); Int8Ty = IRB.getInt8Ty(); Int1Ty = IRB.getInt1Ty(); + Fp16Ty = IRB.getHalfTy(); + Fp32Ty = IRB.getFloatTy(); + Fp64Ty = IRB.getDoubleTy(); SanCovTracePCIndir = M.getOrInsertFunction(SanCovTracePCIndirName, VoidTy, IntptrTy); @@ -470,6 +483,9 @@ IRB.getInt32Ty(), IRB.getInt32Ty()); SanCovTraceCmpFunction[3] = M.getOrInsertFunction(SanCovTraceCmp8, VoidTy, Int64Ty, Int64Ty); + SanCovTraceCmpFunction[4] = M.getOrInsertFunction(SanCovTraceCmpF2, VoidTy, Fp16Ty, Fp16Ty); + SanCovTraceCmpFunction[5] = M.getOrInsertFunction(SanCovTraceCmpF4, VoidTy, Fp32Ty, Fp32Ty); + SanCovTraceCmpFunction[6] = M.getOrInsertFunction(SanCovTraceCmpF8, VoidTy, Fp64Ty, Fp64Ty); SanCovTraceConstCmpFunction[0] = M.getOrInsertFunction( SanCovTraceConstCmp1, SanCovTraceCmpZeroExtAL, VoidTy, Int8Ty, Int8Ty); @@ -479,6 +495,12 @@ SanCovTraceConstCmp4, SanCovTraceCmpZeroExtAL, VoidTy, Int32Ty, Int32Ty); SanCovTraceConstCmpFunction[3] = M.getOrInsertFunction(SanCovTraceConstCmp8, VoidTy, Int64Ty, Int64Ty); + SanCovTraceConstCmpFunction[4] = + M.getOrInsertFunction(SanCovTraceConstCmpF2, VoidTy, Fp16Ty, Fp16Ty); + SanCovTraceConstCmpFunction[5] = + M.getOrInsertFunction(SanCovTraceConstCmpF4, VoidTy, Fp32Ty, Fp32Ty); + SanCovTraceConstCmpFunction[6] = + M.getOrInsertFunction(SanCovTraceConstCmpF8, VoidTy, Fp64Ty, Fp64Ty); // Loads. SanCovLoadFunction[0] = M.getOrInsertFunction(SanCovLoad1, VoidTy, Int8PtrTy); @@ -633,7 +655,7 @@ // // Note that Cmp pruning is controlled by the same flag as the // BB pruning. -static bool IsInterestingCmp(ICmpInst *CMP, const DominatorTree *DT, +static bool IsInterestingCmp(Instruction *CMP, const DominatorTree *DT, const SanitizerCoverageOptions &Options) { if (!Options.NoPrune) if (CMP->hasOneUse()) @@ -678,7 +700,8 @@ SplitAllCriticalEdges(F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests()); SmallVector IndirCalls; SmallVector BlocksToInstrument; - SmallVector CmpTraceTargets; + SmallVector ICmpTraceTargets; + SmallVector FCmpTraceTargets; SmallVector SwitchTraceTargets; SmallVector DivTraceTargets; SmallVector GepTraceTargets; @@ -701,7 +724,10 @@ if (Options.TraceCmp) { if (ICmpInst *CMP = dyn_cast(&Inst)) if (IsInterestingCmp(CMP, DT, Options)) - CmpTraceTargets.push_back(&Inst); + ICmpTraceTargets.push_back(&Inst); + if (FCmpInst *CMP = dyn_cast(&Inst)) + if (IsInterestingCmp(CMP, DT, Options)) + FCmpTraceTargets.push_back(&Inst); if (isa(&Inst)) SwitchTraceTargets.push_back(&Inst); } @@ -728,7 +754,8 @@ InjectCoverage(F, BlocksToInstrument, IsLeafFunc); InjectCoverageForIndirectCalls(F, IndirCalls); - InjectTraceForCmp(F, CmpTraceTargets); + InjectTraceForCmp(F, ICmpTraceTargets); + InjectTraceForCmp(F, FCmpTraceTargets); InjectTraceForSwitch(F, SwitchTraceTargets); InjectTraceForDiv(F, DivTraceTargets); InjectTraceForGep(F, GepTraceTargets); @@ -952,22 +979,40 @@ void ModuleSanitizerCoverage::InjectTraceForCmp( Function &, ArrayRef CmpTraceTargets) { for (auto I : CmpTraceTargets) { - if (ICmpInst *ICMP = dyn_cast(I)) { - IRBuilder<> IRB(ICMP); - Value *A0 = ICMP->getOperand(0); - Value *A1 = ICMP->getOperand(1); - if (!A0->getType()->isIntegerTy()) - continue; + if (isa(I) || isa(I)) { + auto IsIntComparison = isa(I); + IRBuilder<> IRB(I); + Value *A0 = I->getOperand(0); + Value *A1 = I->getOperand(1); + int CallbackIdx; + Type *CallbackArgsTy; uint64_t TypeSize = DL->getTypeStoreSizeInBits(A0->getType()); - int CallbackIdx = TypeSize == 8 ? 0 : - TypeSize == 16 ? 1 : - TypeSize == 32 ? 2 : - TypeSize == 64 ? 3 : -1; + CallbackIdx = IsIntComparison ? + (TypeSize == 8 ? 0 : + TypeSize == 16 ? 1 : + TypeSize == 32 ? 2 : + TypeSize == 64 ? 3 : -1) : + (A0->getType()->isHalfTy() ? 4 : + A0->getType()->isFloatTy() ? 5 : + A0->getType()->isDoubleTy() ? 6 : -1); if (CallbackIdx < 0) continue; + if (IsIntComparison) { + // integer comparison + if (!A0->getType()->isIntegerTy()) + continue; + CallbackArgsTy = Type::getIntNTy(*C, TypeSize); + } else { + // float comparison + if (!A0->getType()->isFloatingPointTy()) + continue; + CallbackArgsTy = (TypeSize == 16 ? Type::getHalfTy(*C) : + TypeSize == 32 ? Type::getFloatTy(*C) : + Type::getDoubleTy(*C)); + } // __sanitizer_cov_trace_cmp((type_size << 32) | predicate, A0, A1); auto CallbackFunc = SanCovTraceCmpFunction[CallbackIdx]; - bool FirstIsConst = isa(A0); - bool SecondIsConst = isa(A1); + bool FirstIsConst = isa(A0) || isa(A0); + bool SecondIsConst = isa(A1) || isa(A1); // If both are const, then we don't need such a comparison. if (FirstIsConst && SecondIsConst) continue; // If only one is const, then make it the first callback argument. @@ -976,10 +1021,8 @@ if (SecondIsConst) std::swap(A0, A1); } - - auto Ty = Type::getIntNTy(*C, TypeSize); - IRB.CreateCall(CallbackFunc, {IRB.CreateIntCast(A0, Ty, true), - IRB.CreateIntCast(A1, Ty, true)}); + IRB.CreateCall(CallbackFunc, {IRB.CreateIntCast(A0, CallbackArgsTy, true), + IRB.CreateIntCast(A1, CallbackArgsTy, true)}); } } } Index: llvm/test/Instrumentation/SanitizerCoverage/cmp-tracing-api-x86_32.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/cmp-tracing-api-x86_32.ll +++ llvm/test/Instrumentation/SanitizerCoverage/cmp-tracing-api-x86_32.ll @@ -12,10 +12,16 @@ ; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp2(i16 zeroext, i16 zeroext) ; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp4(i32 zeroext, i32 zeroext) ; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp8(i64, i64) +; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp_fp2(half, half) +; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp_fp4(float, float) +; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp_fp8(double, double) ; CHECK-DAG: declare void @__sanitizer_cov_trace_const_cmp1(i8 zeroext, i8 zeroext) ; CHECK-DAG: declare void @__sanitizer_cov_trace_const_cmp2(i16 zeroext, i16 zeroext) ; CHECK-DAG: declare void @__sanitizer_cov_trace_const_cmp4(i32 zeroext, i32 zeroext) ; CHECK-DAG: declare void @__sanitizer_cov_trace_const_cmp8(i64, i64) +; CHECK-DAG: declare void @__sanitizer_cov_trace_const_cmp_fp2(half, half) +; CHECK-DAG: declare void @__sanitizer_cov_trace_const_cmp_fp4(float, float) +; CHECK-DAG: declare void @__sanitizer_cov_trace_const_cmp_fp8(double, double) ; CHECK-DAG: declare void @__sanitizer_cov_trace_div4(i32 zeroext) ; CHECK-DAG: declare void @__sanitizer_cov_trace_div8(i64) ; CHECK-DAG: declare void @__sanitizer_cov_trace_gep(i64)