diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGBuiltin.cpp | 24 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 28 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 4 |
3 files changed, 53 insertions, 3 deletions
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 401764a8ddf..69ad762d18e 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -374,6 +374,27 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, "expval"); return RValue::get(Result); } + case Builtin::BI__builtin_assume_aligned: { + Value *PtrValue = EmitScalarExpr(E->getArg(0)); + Value *OffsetValue = + (E->getNumArgs() > 2) ? EmitScalarExpr(E->getArg(2)) : nullptr; + + Value *AlignmentValue = EmitScalarExpr(E->getArg(1)); + ConstantInt *AlignmentCI = cast<ConstantInt>(AlignmentValue); + unsigned Alignment = (unsigned) AlignmentCI->getZExtValue(); + + EmitAlignmentAssumption(PtrValue, Alignment, OffsetValue); + return RValue::get(PtrValue); + } + case Builtin::BI__assume: + case Builtin::BI__builtin_assume: { + if (E->getArg(0)->HasSideEffects(getContext())) + return RValue::get(nullptr); + + Value *ArgValue = EmitScalarExpr(E->getArg(0)); + Value *FnAssume = CGM.getIntrinsic(Intrinsic::assume); + return RValue::get(Builder.CreateCall(FnAssume, ArgValue)); + } case Builtin::BI__builtin_bswap16: case Builtin::BI__builtin_bswap32: case Builtin::BI__builtin_bswap64: { @@ -1510,9 +1531,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BI__noop: // __noop always evaluates to an integer literal zero. return RValue::get(ConstantInt::get(IntTy, 0)); - case Builtin::BI__assume: - // Until LLVM supports assumptions at the IR level, this becomes nothing. - return RValue::get(nullptr); case Builtin::BI_InterlockedExchange: case Builtin::BI_InterlockedExchangePointer: return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Xchg, E); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index fc9e60d1329..426ec7496c4 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -711,6 +711,34 @@ EmitComplexPrePostIncDec(const UnaryOperator *E, LValue LV, return isPre ? IncVal : InVal; } +void CodeGenFunction::EmitAlignmentAssumption(llvm::Value *PtrValue, + unsigned Alignment, + llvm::Value *OffsetValue) { + llvm::Value *PtrIntValue = + Builder.CreatePtrToInt(PtrValue, IntPtrTy, "ptrint"); + + llvm::Value *Mask = llvm::ConstantInt::get(IntPtrTy, + Alignment > 0 ? Alignment - 1 : 0); + if (OffsetValue) { + bool IsOffsetZero = false; + if (llvm::ConstantInt *CI = dyn_cast<llvm::ConstantInt>(OffsetValue)) + IsOffsetZero = CI->isZero(); + + if (!IsOffsetZero) { + if (OffsetValue->getType() != IntPtrTy) + OffsetValue = Builder.CreateIntCast(OffsetValue, IntPtrTy, + /*isSigned*/true, "offsetcast"); + PtrIntValue = Builder.CreateSub(PtrIntValue, OffsetValue, "offsetptr"); + } + } + + llvm::Value *Zero = llvm::ConstantInt::get(IntPtrTy, 0); + llvm::Value *MaskedPtr = Builder.CreateAnd(PtrIntValue, Mask, "maskedptr"); + llvm::Value *InvCond = Builder.CreateICmpEQ(MaskedPtr, Zero, "maskcond"); + + llvm::Value *FnAssume = CGM.getIntrinsic(llvm::Intrinsic::assume); + Builder.CreateCall(FnAssume, InvCond); +} //===----------------------------------------------------------------------===// // LValue Expression Emission diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index c03b9ab26b3..4841b535062 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -1743,6 +1743,10 @@ public: bool isInc, bool isPre); ComplexPairTy EmitComplexPrePostIncDec(const UnaryOperator *E, LValue LV, bool isInc, bool isPre); + + void EmitAlignmentAssumption(llvm::Value *PtrValue, unsigned Alignment, + llvm::Value *OffsetValue = nullptr); + //===--------------------------------------------------------------------===// // Declaration Emission //===--------------------------------------------------------------------===// |