[polly] 1cea25e - [Polly] Remove isConstCall.

Michael Kruse via llvm-commits llvm-commits at lists.llvm.org
Sun Sep 26 01:32:15 PDT 2021


Author: Michael Kruse
Date: 2021-09-26T03:26:43-05:00
New Revision: 1cea25eec90e355c9b072edc1b6e1e9903d7bca4

URL: https://github.com/llvm/llvm-project/commit/1cea25eec90e355c9b072edc1b6e1e9903d7bca4
DIFF: https://github.com/llvm/llvm-project/commit/1cea25eec90e355c9b072edc1b6e1e9903d7bca4.diff

LOG: [Polly] Remove isConstCall.

The function was intended to catch OpenMP functions such as
get_thread_id(). If matched, the call would be considered synthesizable.

There were a few problems with this:

 * get_thread_id() is not 'const' in the sense of have the gcc manual
   defines it: "do not examine any values except their arguments".
   get_thread_id() reads OpenCL runtime libreary global state.
   What was inteded was probably 'speculable'.

 * isConstCall was implemented using mayReadOrWriteMemory(). 'const' is
   stricter than that, mayReadOrWriteMemory is e.g. true for malloc(),
   since it may only read/write addresses that are considered
   inaccessible fro the application. However, malloc is certainly not
   speculable.

 * Values that are isConstCall were not handled consistently throughout
   Polly. In particular, it was not considered for referenced values
   (OpenMP outlining and PollyACC).

Fix by removing special handling for isConstCall entirely.

Added: 
    

Modified: 
    polly/include/polly/Support/SCEVValidator.h
    polly/lib/Analysis/ScopDetection.cpp
    polly/lib/Analysis/ScopInfo.cpp
    polly/lib/Support/SCEVValidator.cpp

Removed: 
    polly/test/ScopInfo/constant_functions_as_unknowns.ll
    polly/test/ScopInfo/constant_functions_multi_dim.ll


################################################################################
diff  --git a/polly/include/polly/Support/SCEVValidator.h b/polly/include/polly/Support/SCEVValidator.h
index cf97655e50bd..5e816aa533b6 100644
--- a/polly/include/polly/Support/SCEVValidator.h
+++ b/polly/include/polly/Support/SCEVValidator.h
@@ -20,24 +20,6 @@ class SCEVConstant;
 namespace polly {
 class ScopDetection;
 
-/// Check if a call is side-effect free and has only constant arguments.
-///
-/// Such calls can be re-generated easily, so we do not need to model them
-/// as scalar dependences.
-///
-/// @param Call The call to check.
-bool isConstCall(llvm::CallInst *Call);
-
-/// Check if some parameters in the affine expression might hide induction
-/// variables. If this is the case, we will try to delinearize the accesses
-/// taking into account this information to possibly obtain a memory access
-/// with more structure. Currently we assume that each parameter that
-/// comes from a function call might depend on a (virtual) induction variable.
-/// This covers calls to 'get_global_id' and 'get_local_id' as they commonly
-/// arise in OpenCL code, while not catching any false-positives in our current
-/// tests.
-bool hasIVParams(const llvm::SCEV *Expr);
-
 /// Find the loops referenced from a SCEV expression.
 ///
 /// @param Expr The SCEV expression to scan for loops.

diff  --git a/polly/lib/Analysis/ScopDetection.cpp b/polly/lib/Analysis/ScopDetection.cpp
index a4a52248535a..bf9d7abbbcec 100644
--- a/polly/lib/Analysis/ScopDetection.cpp
+++ b/polly/lib/Analysis/ScopDetection.cpp
@@ -1134,7 +1134,7 @@ bool ScopDetection::isValidAccess(Instruction *Inst, const SCEV *AF,
   } else if (PollyDelinearize && !IsVariantInNonAffineLoop) {
     Context.Accesses[BP].push_back({Inst, AF});
 
-    if (!IsAffine || hasIVParams(AF))
+    if (!IsAffine)
       Context.NonAffineAccesses.insert(
           std::make_pair(BP, LI.getLoopFor(Inst->getParent())));
   } else if (!AllowNonAffine && !IsAffine) {

diff  --git a/polly/lib/Analysis/ScopInfo.cpp b/polly/lib/Analysis/ScopInfo.cpp
index d0ade9fd4387..60a54f1ccb80 100644
--- a/polly/lib/Analysis/ScopInfo.cpp
+++ b/polly/lib/Analysis/ScopInfo.cpp
@@ -1468,37 +1468,6 @@ const SCEV *Scop::getRepresentingInvariantLoadSCEV(const SCEV *E) const {
   return SCEVSensitiveParameterRewriter::rewrite(E, *SE, InvEquivClassVMap);
 }
 
-// This table of function names is used to translate parameter names in more
-// human-readable names. This makes it easier to interpret Polly analysis
-// results.
-StringMap<std::string> KnownNames = {
-    {"_Z13get_global_idj", "global_id"},
-    {"_Z12get_local_idj", "local_id"},
-    {"_Z15get_global_sizej", "global_size"},
-    {"_Z14get_local_sizej", "local_size"},
-    {"_Z12get_work_dimv", "work_dim"},
-    {"_Z17get_global_offsetj", "global_offset"},
-    {"_Z12get_group_idj", "group_id"},
-    {"_Z14get_num_groupsj", "num_groups"},
-};
-
-static std::string getCallParamName(CallInst *Call) {
-  std::string Result;
-  raw_string_ostream OS(Result);
-  std::string Name = Call->getCalledFunction()->getName().str();
-
-  auto Iterator = KnownNames.find(Name);
-  if (Iterator != KnownNames.end())
-    Name = "__" + Iterator->getValue();
-  OS << Name;
-  for (auto &Operand : Call->arg_operands()) {
-    ConstantInt *Op = cast<ConstantInt>(&Operand);
-    OS << "_" << Op->getValue();
-  }
-  OS.flush();
-  return Result;
-}
-
 void Scop::createParameterId(const SCEV *Parameter) {
   assert(Parameters.count(Parameter));
   assert(!ParameterIds.count(Parameter));
@@ -1507,11 +1476,8 @@ void Scop::createParameterId(const SCEV *Parameter) {
 
   if (const SCEVUnknown *ValueParameter = dyn_cast<SCEVUnknown>(Parameter)) {
     Value *Val = ValueParameter->getValue();
-    CallInst *Call = dyn_cast<CallInst>(Val);
 
-    if (Call && isConstCall(Call)) {
-      ParameterName = getCallParamName(Call);
-    } else if (UseInstructionNames) {
+    if (UseInstructionNames) {
       // If this parameter references a specific Value and this value has a name
       // we use this name as it is likely to be unique and more useful than just
       // a number.

diff  --git a/polly/lib/Support/SCEVValidator.cpp b/polly/lib/Support/SCEVValidator.cpp
index f6b601ae317d..002674375df0 100644
--- a/polly/lib/Support/SCEVValidator.cpp
+++ b/polly/lib/Support/SCEVValidator.cpp
@@ -117,17 +117,6 @@ raw_ostream &operator<<(raw_ostream &OS, class ValidatorResult &VR) {
   return OS;
 }
 
-bool polly::isConstCall(llvm::CallInst *Call) {
-  if (Call->mayReadOrWriteMemory())
-    return false;
-
-  for (auto &Operand : Call->arg_operands())
-    if (!isa<ConstantInt>(&Operand))
-      return false;
-
-  return true;
-}
-
 /// Check if a SCEV is valid in a SCoP.
 struct SCEVValidator
     : public SCEVVisitor<SCEVValidator, class ValidatorResult> {
@@ -353,18 +342,6 @@ struct SCEVValidator
     return ValidatorResult(SCEVType::PARAM, S);
   }
 
-  ValidatorResult visitCallInstruction(Instruction *I, const SCEV *S) {
-    assert(I->getOpcode() == Instruction::Call && "Call instruction expected");
-
-    if (R->contains(I)) {
-      auto Call = cast<CallInst>(I);
-
-      if (!isConstCall(Call))
-        return ValidatorResult(SCEVType::INVALID, S);
-    }
-    return ValidatorResult(SCEVType::PARAM, S);
-  }
-
   ValidatorResult visitLoadInstruction(Instruction *I, const SCEV *S) {
     if (R->contains(I) && ILS) {
       ILS->insert(cast<LoadInst>(I));
@@ -454,8 +431,6 @@ struct SCEVValidator
         return visitSDivInstruction(I, Expr);
       case Instruction::SRem:
         return visitSRemInstruction(I, Expr);
-      case Instruction::Call:
-        return visitCallInstruction(I, Expr);
       default:
         return visitGenericInst(I, Expr);
       }
@@ -470,34 +445,6 @@ struct SCEVValidator
   }
 };
 
-class SCEVHasIVParams {
-  bool HasIVParams = false;
-
-public:
-  SCEVHasIVParams() {}
-
-  bool follow(const SCEV *S) {
-    const SCEVUnknown *Unknown = dyn_cast<SCEVUnknown>(S);
-    if (!Unknown)
-      return true;
-
-    CallInst *Call = dyn_cast<CallInst>(Unknown->getValue());
-
-    if (!Call)
-      return true;
-
-    if (isConstCall(Call)) {
-      HasIVParams = true;
-      return false;
-    }
-
-    return true;
-  }
-
-  bool isDone() { return HasIVParams; }
-  bool hasIVParams() { return HasIVParams; }
-};
-
 /// Check whether a SCEV refers to an SSA name defined inside a region.
 class SCEVInRegionDependences {
   const Region *R;
@@ -515,11 +462,6 @@ class SCEVInRegionDependences {
     if (auto Unknown = dyn_cast<SCEVUnknown>(S)) {
       Instruction *Inst = dyn_cast<Instruction>(Unknown->getValue());
 
-      CallInst *Call = dyn_cast<CallInst>(Unknown->getValue());
-
-      if (Call && isConstCall(Call))
-        return false;
-
       if (Inst) {
         // When we invariant load hoist a load, we first make sure that there
         // can be no dependences created by it in the Scop region. So, we should
@@ -623,13 +565,6 @@ void findValues(const SCEV *Expr, ScalarEvolution &SE,
   ST.visitAll(Expr);
 }
 
-bool hasIVParams(const SCEV *Expr) {
-  SCEVHasIVParams HasIVParams;
-  SCEVTraversal<SCEVHasIVParams> ST(HasIVParams);
-  ST.visitAll(Expr);
-  return HasIVParams.hasIVParams();
-}
-
 bool hasScalarDepsInsideRegion(const SCEV *Expr, const Region *R,
                                llvm::Loop *Scope, bool AllowLoops,
                                const InvariantLoadsSetTy &ILS) {

diff  --git a/polly/test/ScopInfo/constant_functions_as_unknowns.ll b/polly/test/ScopInfo/constant_functions_as_unknowns.ll
deleted file mode 100644
index 2210d4b9e67f..000000000000
--- a/polly/test/ScopInfo/constant_functions_as_unknowns.ll
+++ /dev/null
@@ -1,67 +0,0 @@
-; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
-
-target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-unknown-linux-gnu"
-
-; CHECK:      Context:
-; CHECK-NEXT: [__global_id_0] -> {  : -9223372036854775808 <= __global_id_0 <= 9223372036854775807 }
-; CHECK-NEXT: Assumed Context:
-; CHECK-NEXT: [__global_id_0] -> {  :  }
-; CHECK-NEXT: Invalid Context:
-; CHECK-NEXT: [__global_id_0] -> {  : false }
-; CHECK:      p0: %__global_id_0
-; CHECK-NEXT: Arrays {
-; CHECK-NEXT:     i64 MemRef_A[*]; // Element size 8
-; CHECK-NEXT: }
-; CHECK-NEXT: Arrays (Bounds as pw_affs) {
-; CHECK-NEXT:     i64 MemRef_A[*]; // Element size 8
-; CHECK-NEXT: }
-; CHECK-NEXT: Alias Groups (0):
-; CHECK-NEXT:     n/a
-; CHECK-NEXT: Statements {
-; CHECK-NEXT: 	Stmt_bb
-; CHECK-NEXT:         Domain :=
-; CHECK-NEXT:             [__global_id_0] -> { Stmt_bb[] };
-; CHECK-NEXT:         Schedule :=
-; CHECK-NEXT:             [__global_id_0] -> { Stmt_bb[] -> [] };
-; CHECK-NEXT:         MustWriteAccess :=	[Reduction Type: NONE] [Scalar: 0]
-; CHECK-NEXT:             [__global_id_0] -> { Stmt_bb[] -> MemRef_A[__global_id_0] };
-; CHECK-NEXT: }
-
-define void @globalid(i64* nocapture %A) local_unnamed_addr #0 !kernel_arg_addr_space !2 !kernel_arg_access_qual !3 !kernel_arg_type !4 !kernel_arg_base_type !4 !kernel_arg_type_qual !5 {
-entry:
-  br label %next
-
-next:
-  br i1 true, label %bb, label %exit
-
-bb:
-  %__global_id_0 = tail call i64 @_Z13get_global_idj(i32 0) #2
-  %arrayidx = getelementptr inbounds i64, i64* %A, i64 %__global_id_0
-  store i64 0, i64* %arrayidx, align 8, !tbaa !6
-  br label %exit
-
-exit:
-  ret void
-}
-
-; Function Attrs: nounwind readnone
-declare i64 @_Z13get_global_idj(i32) local_unnamed_addr #1
-
-attributes #0 = { nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-__global_id_0s"="false" "less-precise-fpmad"="false" "frame-pointer"="all" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
-attributes #1 = { nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-__global_id_0s"="false" "less-precise-fpmad"="false" "frame-pointer"="all" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
-attributes #2 = { nounwind readnone }
-
-!llvm.module.flags = !{!0}
-!llvm.ident = !{!1}
-
-!0 = !{i32 1, !"wchar_size", i32 4}
-!1 = !{!"clang version 5.0.0 (trunk 303846) (llvm/trunk 303834)"}
-!2 = !{i32 1}
-!3 = !{!"none"}
-!4 = !{!"long*"}
-!5 = !{!""}
-!6 = !{!7, !7, i64 0}
-!7 = !{!"long", !8, i64 0}
-!8 = !{!"omnipotent char", !9, i64 0}
-!9 = !{!"Simple C/C++ TBAA"}

diff  --git a/polly/test/ScopInfo/constant_functions_multi_dim.ll b/polly/test/ScopInfo/constant_functions_multi_dim.ll
deleted file mode 100644
index bc729a59d5c6..000000000000
--- a/polly/test/ScopInfo/constant_functions_multi_dim.ll
+++ /dev/null
@@ -1,118 +0,0 @@
-; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-scops -analyze \
-; RUN:                -polly-detect-full-functions < %s | FileCheck %s
-
-target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
-
-; CHECK:         Statements {
-; CHECK-NEXT:    	Stmt_entry_split
-; CHECK-NEXT:            Domain :=
-; CHECK-NEXT:                [N, __global_id_0, __global_id_1] -> { Stmt_entry_split[] };
-; CHECK-NEXT:            Schedule :=
-; CHECK-NEXT:                [N, __global_id_0, __global_id_1] -> { Stmt_entry_split[] -> [0, 0] };
-; CHECK-NEXT:            MustWriteAccess :=	[Reduction Type: NONE] [Scalar: 1]
-; CHECK-NEXT:                [N, __global_id_0, __global_id_1] -> { Stmt_entry_split[] -> MemRef_acc_0_lcssa__phi[] };
-; CHECK-NEXT:    	Stmt_for_inc_lr_ph
-; CHECK-NEXT:            Domain :=
-; CHECK-NEXT:                [N, __global_id_0, __global_id_1] -> { Stmt_for_inc_lr_ph[] : N > 0 };
-; CHECK-NEXT:            Schedule :=
-; CHECK-NEXT:                [N, __global_id_0, __global_id_1] -> { Stmt_for_inc_lr_ph[] -> [1, 0] };
-; CHECK-NEXT:            MustWriteAccess :=	[Reduction Type: NONE] [Scalar: 1]
-; CHECK-NEXT:                [N, __global_id_0, __global_id_1] -> { Stmt_for_inc_lr_ph[] -> MemRef_acc_03__phi[] };
-; CHECK-NEXT:    	Stmt_for_inc
-; CHECK-NEXT:            Domain :=
-; CHECK-NEXT:                [N, __global_id_0, __global_id_1] -> { Stmt_for_inc[i0] : 0 <= i0 < N };
-; CHECK-NEXT:            Schedule :=
-; CHECK-NEXT:                [N, __global_id_0, __global_id_1] -> { Stmt_for_inc[i0] -> [2, i0] };
-; CHECK-NEXT:            MustWriteAccess :=	[Reduction Type: NONE] [Scalar: 1]
-; CHECK-NEXT:                [N, __global_id_0, __global_id_1] -> { Stmt_for_inc[i0] -> MemRef_acc_03__phi[] };
-; CHECK-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 1]
-; CHECK-NEXT:                [N, __global_id_0, __global_id_1] -> { Stmt_for_inc[i0] -> MemRef_acc_03__phi[] };
-; CHECK-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 0]
-; CHECK-NEXT:                [N, __global_id_0, __global_id_1] -> { Stmt_for_inc[i0] -> MemRef_A[__global_id_0, i0] };
-; CHECK-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 0]
-; CHECK-NEXT:                [N, __global_id_0, __global_id_1] -> { Stmt_for_inc[i0] -> MemRef_B[i0, __global_id_1] };
-; CHECK-NEXT:            MustWriteAccess :=	[Reduction Type: NONE] [Scalar: 1]
-; CHECK-NEXT:                [N, __global_id_0, __global_id_1] -> { Stmt_for_inc[i0] -> MemRef__lcssa__phi[] };
-; CHECK-NEXT:    	Stmt_for_cond_for_end_crit_edge
-; CHECK-NEXT:            Domain :=
-; CHECK-NEXT:                [N, __global_id_0, __global_id_1] -> { Stmt_for_cond_for_end_crit_edge[] : N > 0 };
-; CHECK-NEXT:            Schedule :=
-; CHECK-NEXT:                [N, __global_id_0, __global_id_1] -> { Stmt_for_cond_for_end_crit_edge[] -> [3, 0] };
-; CHECK-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 1]
-; CHECK-NEXT:                [N, __global_id_0, __global_id_1] -> { Stmt_for_cond_for_end_crit_edge[] -> MemRef__lcssa__phi[] };
-; CHECK-NEXT:            MustWriteAccess :=	[Reduction Type: NONE] [Scalar: 1]
-; CHECK-NEXT:                [N, __global_id_0, __global_id_1] -> { Stmt_for_cond_for_end_crit_edge[] -> MemRef_acc_0_lcssa__phi[] };
-; CHECK-NEXT:    	Stmt_for_end
-; CHECK-NEXT:            Domain :=
-; CHECK-NEXT:                [N, __global_id_0, __global_id_1] -> { Stmt_for_end[] };
-; CHECK-NEXT:            Schedule :=
-; CHECK-NEXT:                [N, __global_id_0, __global_id_1] -> { Stmt_for_end[] -> [4, 0] };
-; CHECK-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 1]
-; CHECK-NEXT:                [N, __global_id_0, __global_id_1] -> { Stmt_for_end[] -> MemRef_acc_0_lcssa__phi[] };
-; CHECK-NEXT:            MustWriteAccess :=	[Reduction Type: NONE] [Scalar: 0]
-; CHECK-NEXT:                [N, __global_id_0, __global_id_1] -> { Stmt_for_end[] -> MemRef_C[__global_id_0, __global_id_1] };
-; CHECK-NEXT:    }
-
-
-; Function Attrs: noinline nounwind uwtable
-define void @mat_mul(float* %C, float* %A, float* %B, i64 %N) #0 !kernel_arg_addr_space !2 !kernel_arg_access_qual !3 !kernel_arg_type !4 !kernel_arg_base_type !4 !kernel_arg_type_qual !5 {
-entry:
-  br label %entry.split
-
-entry.split:                                      ; preds = %entry
-  %call = tail call i64 @_Z13get_global_idj(i32 0) #3
-  %call1 = tail call i64 @_Z13get_global_idj(i32 1) #3
-  %cmp1 = icmp sgt i64 %N, 0
-  %mul = mul nsw i64 %call, %N
-  br i1 %cmp1, label %for.inc.lr.ph, label %for.end
-
-for.inc.lr.ph:                                    ; preds = %entry.split
-  br label %for.inc
-
-for.inc:                                          ; preds = %for.inc.lr.ph, %for.inc
-  %acc.03 = phi float [ 0.000000e+00, %for.inc.lr.ph ], [ %tmp6, %for.inc ]
-  %m.02 = phi i64 [ 0, %for.inc.lr.ph ], [ %inc, %for.inc ]
-  %add = add nsw i64 %m.02, %mul
-  %arrayidx = getelementptr inbounds float, float* %A, i64 %add
-  %tmp = load float, float* %arrayidx, align 4
-  %mul2 = mul nsw i64 %m.02, %N
-  %add3 = add nsw i64 %mul2, %call1
-  %arrayidx4 = getelementptr inbounds float, float* %B, i64 %add3
-  %tmp5 = load float, float* %arrayidx4, align 4
-  %tmp6 = tail call float @llvm.fmuladd.f32(float %tmp, float %tmp5, float %acc.03)
-  %inc = add nuw nsw i64 %m.02, 1
-  %exitcond = icmp ne i64 %inc, %N
-  br i1 %exitcond, label %for.inc, label %for.cond.for.end_crit_edge
-
-for.cond.for.end_crit_edge:                       ; preds = %for.inc
-  %.lcssa = phi float [ %tmp6, %for.inc ]
-  br label %for.end
-
-for.end:                                          ; preds = %for.cond.for.end_crit_edge, %entry.split
-  %acc.0.lcssa = phi float [ %.lcssa, %for.cond.for.end_crit_edge ], [ 0.000000e+00, %entry.split ]
-  %add7 = add nsw i64 %mul, %call1
-  %arrayidx8 = getelementptr inbounds float, float* %C, i64 %add7
-  store float %acc.0.lcssa, float* %arrayidx8, align 4
-  ret void
-}
-
-; Function Attrs: nounwind readnone
-declare i64 @_Z13get_global_idj(i32) #1
-
-; Function Attrs: nounwind readnone speculatable
-declare float @llvm.fmuladd.f32(float, float, float) #2
-
-attributes #0 = { noinline nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "frame-pointer"="all" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
-attributes #1 = { nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "frame-pointer"="all" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
-attributes #2 = { nounwind readnone speculatable }
-attributes #3 = { nounwind readnone }
-
-!llvm.module.flags = !{!0}
-!llvm.ident = !{!1}
-
-!0 = !{i32 1, !"wchar_size", i32 4}
-!1 = !{!"clang version 5.0.0 (trunk 303846) (llvm/trunk 303834)"}
-!2 = !{i32 1, i32 1, i32 1, i32 0}
-!3 = !{!"none", !"none", !"none", !"none"}
-!4 = !{!"float*", !"float*", !"float*", !"long"}
-!5 = !{!"", !"", !"", !""}


        


More information about the llvm-commits mailing list