Index: lib/Analysis/ScopDetection.cpp =================================================================== --- lib/Analysis/ScopDetection.cpp +++ lib/Analysis/ScopDetection.cpp @@ -59,6 +59,7 @@ #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/IR/DebugInfo.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IR/LLVMContext.h" @@ -311,7 +312,60 @@ if (CalledFunction == 0) return false; - // TODO: Intrinsics. + // Check if we can handle the intrinsic call. + if (auto *IT = dyn_cast(&CI)) { + switch (IT->getIntrinsicID()) { + // Basic mathematical intrinsics are supported. + case llvm::Intrinsic::sqrt: + case llvm::Intrinsic::powi: + case llvm::Intrinsic::sin: + case llvm::Intrinsic::cos: + case llvm::Intrinsic::pow: + case llvm::Intrinsic::exp: + case llvm::Intrinsic::exp2: + case llvm::Intrinsic::log: + case llvm::Intrinsic::log10: + case llvm::Intrinsic::log2: + case llvm::Intrinsic::fma: + case llvm::Intrinsic::fmuladd: + case llvm::Intrinsic::fabs: + case llvm::Intrinsic::copysign: + case llvm::Intrinsic::floor: + case llvm::Intrinsic::ceil: + case llvm::Intrinsic::trunc: + case llvm::Intrinsic::nearbyint: + case llvm::Intrinsic::round: + // Basic bitwise intrinsics are supported. + case llvm::Intrinsic::bswap: + case llvm::Intrinsic::ctpop: + case llvm::Intrinsic::ctlz: + case llvm::Intrinsic::cttz: + // Conversion of floating points is supported. + case llvm::Intrinsic::convert_to_fp16: + case llvm::Intrinsic::convert_from_fp16: + case llvm::Intrinsic::convertfsi: + case llvm::Intrinsic::convertsif: + // Lifetime markers are supported. + case llvm::Intrinsic::lifetime_start: + case llvm::Intrinsic::lifetime_end: + // Invariant markers are supported. + case llvm::Intrinsic::invariant_start: + case llvm::Intrinsic::invariant_end: + // Arbitrary annotations are supported. + case llvm::Intrinsic::var_annotation: + case llvm::Intrinsic::ptr_annotation: + case llvm::Intrinsic::annotation: + // Some intrinsics can be ignored, thus are supported. + case llvm::Intrinsic::donothing: + case llvm::Intrinsic::assume: + case llvm::Intrinsic::expect: + return true; + default: + // Other intrinsics are not supported. + break; + } + } + return false; } Index: test/ScopDetect/intrinsics.ll =================================================================== --- /dev/null +++ test/ScopDetect/intrinsics.ll @@ -0,0 +1,111 @@ +; RUN: opt %loadPolly -basicaa -polly-detect -analyze < %s | FileCheck %s +; +; CHECK: Valid Region for Scop: for.cond => for.end23 +; +; #include "math.h" +; +; void jd_intrinsics(int *restrict A, float *restrict B) { +; for (int i = 0; i < 1024; i++) +; A[i] = pow(ceil(log10(sqrt(i))), floor(log2(999))); +; for (int i = 0; i < 1024; i++) +; B[i] = pow(fabs(log(sin(i)) + exp2(cos(i))), exp(23)); +; } +; +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +define void @jd_intrinsics(i32* noalias %A, float* noalias %B) #0 { +entry: + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + %indvars.iv1 = phi i64 [ %indvars.iv.next2, %for.inc ], [ 0, %entry ] + %exitcond3 = icmp ne i64 %indvars.iv1, 1024 + br i1 %exitcond3, label %for.body, label %for.end + +for.body: ; preds = %for.cond + %tmp = trunc i64 %indvars.iv1 to i32 + %conv = sitofp i32 %tmp to double + %tmp4 = call double @llvm.sqrt.f64(double %conv) + %call = call double @llvm.log10(double %tmp4) + %call1 = call double @llvm.ceil(double %call) + %call2 = call double @llvm.log2.f64(double 9.990000e+02) + %call3 = call double @llvm.floor(double %call2) + %tmp5 = call double @llvm.pow.f64(double %call1, double %call3) + %conv4 = fptosi double %tmp5 to i32 + %arrayidx = getelementptr inbounds i32* %A, i64 %indvars.iv1 + store i32 %conv4, i32* %arrayidx, align 4 + br label %for.inc + +for.inc: ; preds = %for.body + %indvars.iv.next2 = add nuw nsw i64 %indvars.iv1, 1 + br label %for.cond + +for.end: ; preds = %for.cond + br label %for.cond6 + +for.cond6: ; preds = %for.inc21, %for.end + %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc21 ], [ 0, %for.end ] + %exitcond = icmp ne i64 %indvars.iv, 1024 + br i1 %exitcond, label %for.body9, label %for.end23 + +for.body9: ; preds = %for.cond6 + %tmp6 = trunc i64 %indvars.iv to i32 + %conv10 = sitofp i32 %tmp6 to double + %call11 = call double @llvm.sin(double %conv10) + %call12 = call double @llvm.log(double %call11) + %tmp7 = trunc i64 %indvars.iv to i32 + %conv13 = sitofp i32 %tmp7 to double + %call14 = call double @llvm.cos(double %conv13) + %call15 = call double @llvm.exp2(double %call14) + %add = fadd fast double %call12, %call15 + %call16 = call double @llvm.fabs(double %add) + %call17 = call double @llvm.exp(double 2.300000e+01) + %tmp8 = call double @llvm.pow.f64(double %call16, double %call17) + %conv18 = fptrunc double %tmp8 to float + %arrayidx20 = getelementptr inbounds float* %B, i64 %indvars.iv + store float %conv18, float* %arrayidx20, align 4 + br label %for.inc21 + +for.inc21: ; preds = %for.body9 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + br label %for.cond6 + +for.end23: ; preds = %for.cond6 + ret void +} + +; Function Attrs: nounwind readnone +declare double @llvm.ceil(double) + +; Function Attrs: nounwind readnone +declare double @llvm.log10(double) + +; Function Attrs: nounwind readnone +declare double @llvm.sqrt.f64(double) + +; Function Attrs: nounwind readnone +declare double @llvm.floor(double) + +; Function Attrs: nounwind readnone +declare double @llvm.log2.f64(double) + +; Function Attrs: nounwind readnone +declare double @llvm.pow.f64(double, double) + +; Function Attrs: nounwind readnone +declare double @llvm.fabs(double) + +; Function Attrs: nounwind readnone +declare double @llvm.log(double) + +; Function Attrs: nounwind readnone +declare double @llvm.sin(double) + +; Function Attrs: nounwind readnone +declare double @llvm.exp2(double) + +; Function Attrs: nounwind readnone +declare double @llvm.cos(double) + +; Function Attrs: nounwind readnone +declare double @llvm.exp(double)