diff options
| -rw-r--r-- | polly/include/polly/CodeGen/RuntimeDebugBuilder.h | 112 | ||||
| -rw-r--r-- | polly/lib/CodeGen/BlockGenerators.cpp | 15 | ||||
| -rw-r--r-- | polly/lib/CodeGen/RuntimeDebugBuilder.cpp | 109 | ||||
| -rw-r--r-- | polly/test/Isl/CodeGen/RuntimeDebugBuilder/combine_different_values.c | 23 | ||||
| -rw-r--r-- | polly/test/Isl/CodeGen/RuntimeDebugBuilder/combine_different_values.ll | 179 |
5 files changed, 359 insertions, 79 deletions
diff --git a/polly/include/polly/CodeGen/RuntimeDebugBuilder.h b/polly/include/polly/CodeGen/RuntimeDebugBuilder.h index a22416f2bee..7ea1115e158 100644 --- a/polly/include/polly/CodeGen/RuntimeDebugBuilder.h +++ b/polly/include/polly/CodeGen/RuntimeDebugBuilder.h @@ -30,30 +30,21 @@ namespace polly { /// run time. struct RuntimeDebugBuilder { - /// @brief Print a string to stdout. + /// @brief Print a set of LLVM-IR Values or StringRefs via printf /// - /// @param String The string to print. - static void createStrPrinter(PollyIRBuilder &Builder, - const std::string &String); - - /// @brief Print a value to stdout. - /// - /// @param V The value to print. - /// - /// @note Only integer, floating point and pointer values up to 64bit are - /// supported. - static void createValuePrinter(PollyIRBuilder &Builder, llvm::Value *V); - - /// @brief Add a call to the fflush function with no file pointer given. - /// - /// This call will flush all opened file pointers including stdout and stderr. - static void createFlush(PollyIRBuilder &Builder); - - /// @brief Get a reference to the 'printf' function. + /// This function emits a call to printf that will print the given arguments. + /// It is useful for debugging CPU programs. All arguments given in this list + /// will be automatically concatenated and the resulting string will be + /// printed atomically. We also support ArrayRef arguments, which can be used + /// to provide of id values. /// - /// If the current module does not yet contain a reference to printf, we - /// insert a reference to it. Otherwise the existing reference is returned. - static llvm::Function *getPrintF(PollyIRBuilder &Builder); + /// @param Builder The builder used to emit the printer calls. + /// @param Args The list of values to print. + template <typename... Args> + static void createCPUPrinter(PollyIRBuilder &Builder, Args... args) { + std::vector<llvm::Value *> Vector; + createPrinter(Builder, /* CPU */ false, Vector, args...); + } /// @brief Print a set of LLVM-IR Values or StringRefs on an NVIDIA GPU. /// @@ -69,52 +60,77 @@ struct RuntimeDebugBuilder { template <typename... Args> static void createGPUPrinter(PollyIRBuilder &Builder, Args... args) { std::vector<llvm::Value *> Vector; - createGPUVAPrinter(Builder, Vector, args...); + createPrinter(Builder, /* GPU */ true, Vector, args...); } private: - /// @brief GPU printing - Print a list of LLVM Values. - /// - static void createGPUVAPrinter(PollyIRBuilder &Builder, - llvm::ArrayRef<llvm::Value *> Values); - - /// @brief GPU printing - Handle Values. + /// @brief Handle Values. template <typename... Args> - static void createGPUVAPrinter(PollyIRBuilder &Builder, - std::vector<llvm::Value *> &Values, - llvm::Value *Value, Args... args) { + static void createPrinter(PollyIRBuilder &Builder, bool UseGPU, + std::vector<llvm::Value *> &Values, + llvm::Value *Value, Args... args) { Values.push_back(Value); - createGPUVAPrinter(Builder, Values, args...); + createPrinter(Builder, UseGPU, Values, args...); } - /// @brief GPU printing - Handle StringRefs. + /// @brief Handle StringRefs. template <typename... Args> - static void createGPUVAPrinter(PollyIRBuilder &Builder, - std::vector<llvm::Value *> &Values, - llvm::StringRef String, Args... args) { + static void createPrinter(PollyIRBuilder &Builder, bool UseGPU, + std::vector<llvm::Value *> &Values, + llvm::StringRef String, Args... args) { Values.push_back(Builder.CreateGlobalStringPtr(String, "", 4)); - createGPUVAPrinter(Builder, Values, args...); + createPrinter(Builder, UseGPU, Values, args...); } - /// @brief GPU printing - Handle ArrayRefs. + /// @brief Handle ArrayRefs. template <typename... Args> - static void createGPUVAPrinter(PollyIRBuilder &Builder, - std::vector<llvm::Value *> &Values, - llvm::ArrayRef<llvm::Value *> Array, - Args... args) { + static void createPrinter(PollyIRBuilder &Builder, bool UseGPU, + std::vector<llvm::Value *> &Values, + llvm::ArrayRef<llvm::Value *> Array, Args... args) { if (Array.size() >= 2) - createGPUVAPrinter( - Builder, Values, Array[0], " ", - llvm::ArrayRef<llvm::Value *>(&Array[1], Array.size() - 1), args...); + createPrinter(Builder, Values, Array[0], " ", + llvm::ArrayRef<llvm::Value *>(&Array[1], Array.size() - 1), + args...); else if (Array.size() == 1) - createGPUVAPrinter(Builder, Values, Array[0], args...); + createPrinter(Builder, UseGPU, Values, Array[0], args...); else - createGPUVAPrinter(Builder, Values, args...); + createPrinter(Builder, UseGPU, Values, args...); } + /// @brief Print a list of Values. + static void createPrinter(PollyIRBuilder &Builder, bool UseGPU, + llvm::ArrayRef<llvm::Value *> Values); + + /// @brief Print a list of Values on a GPU. + static void createGPUPrinterT(PollyIRBuilder &Builder, + llvm::ArrayRef<llvm::Value *> Values); + + /// @brief Print a list of Values on a CPU. + static void createCPUPrinterT(PollyIRBuilder &Builder, + llvm::ArrayRef<llvm::Value *> Values); + + /// @brief Get a reference to the 'printf' function. + /// + /// If the current module does not yet contain a reference to printf, we + /// insert a reference to it. Otherwise the existing reference is returned. + static llvm::Function *getPrintF(PollyIRBuilder &Builder); + + /// @brief Call printf + /// + /// @param Builder The builder used to insert the code. + /// @param Format The format string. + /// @param Values The set of values to print. + static void createPrintF(PollyIRBuilder &Builder, std::string Format, + llvm::ArrayRef<llvm::Value *> Values); + /// @brief Get (and possibly insert) a vprintf declaration into the module. static llvm::Function *getVPrintF(PollyIRBuilder &Builder); + /// @brief Call fflush + /// + /// @parma Builder The builder used to insert the code. + static void createFlush(PollyIRBuilder &Builder); + /// @brief Get (and possibly insert) a NVIDIA address space cast call. static llvm::Function *getAddressSpaceCast(PollyIRBuilder &Builder, unsigned Src, unsigned Dst, diff --git a/polly/lib/CodeGen/BlockGenerators.cpp b/polly/lib/CodeGen/BlockGenerators.cpp index 228a0c6ff41..6a4749c1e70 100644 --- a/polly/lib/CodeGen/BlockGenerators.cpp +++ b/polly/lib/CodeGen/BlockGenerators.cpp @@ -17,6 +17,7 @@ #include "polly/CodeGen/BlockGenerators.h" #include "polly/CodeGen/CodeGeneration.h" #include "polly/CodeGen/IslExprBuilder.h" +#include "polly/CodeGen/RuntimeDebugBuilder.h" #include "polly/Options.h" #include "polly/Support/GICHelper.h" #include "polly/Support/SCEVValidator.h" @@ -41,6 +42,11 @@ static cl::opt<bool> Aligned("enable-polly-aligned", cl::Hidden, cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory)); +static cl::opt<bool> DebugPrinting( + "polly-codegen-add-debug-printing", + cl::desc("Add printf calls that show the values loaded/stored."), + cl::Hidden, cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory)); + bool polly::canSynthesize(const Value *V, const llvm::LoopInfo *LI, ScalarEvolution *SE, const Region *R) { if (!V || !SE->isSCEVable(V->getType())) @@ -208,6 +214,11 @@ Value *BlockGenerator::generateScalarLoad(ScopStmt &Stmt, const LoadInst *Load, generateLocationAccessed(Stmt, Load, Pointer, BBMap, LTS, NewAccesses); Value *ScalarLoad = Builder.CreateAlignedLoad( NewPointer, Load->getAlignment(), Load->getName() + "_p_scalar_"); + + if (DebugPrinting) + RuntimeDebugBuilder::createCPUPrinter(Builder, "Load from ", NewPointer, + ": ", ScalarLoad, "\n"); + return ScalarLoad; } @@ -220,6 +231,10 @@ void BlockGenerator::generateScalarStore(ScopStmt &Stmt, const StoreInst *Store, Value *ValueOperand = getNewValue(Stmt, Store->getValueOperand(), BBMap, LTS, getLoopForInst(Store)); + if (DebugPrinting) + RuntimeDebugBuilder::createCPUPrinter(Builder, "Store to ", NewPointer, + ": ", ValueOperand, "\n"); + Builder.CreateAlignedStore(ValueOperand, NewPointer, Store->getAlignment()); } diff --git a/polly/lib/CodeGen/RuntimeDebugBuilder.cpp b/polly/lib/CodeGen/RuntimeDebugBuilder.cpp index 5820d31a341..dd2432ad31d 100644 --- a/polly/lib/CodeGen/RuntimeDebugBuilder.cpp +++ b/polly/lib/CodeGen/RuntimeDebugBuilder.cpp @@ -95,8 +95,72 @@ RuntimeDebugBuilder::getGPUThreadIdentifiers(PollyIRBuilder &Builder) { return Identifiers; } -void RuntimeDebugBuilder::createGPUVAPrinter(PollyIRBuilder &Builder, - ArrayRef<Value *> Values) { +void RuntimeDebugBuilder::createPrinter(PollyIRBuilder &Builder, bool IsGPU, + ArrayRef<Value *> Values) { + if (IsGPU) + createGPUPrinterT(Builder, Values); + else + createCPUPrinterT(Builder, Values); +} + +static std::tuple<std::string, std::vector<Value *>> +prepareValuesForPrinting(PollyIRBuilder &Builder, ArrayRef<Value *> Values) { + std::string FormatString; + std::vector<Value *> ValuesToPrint; + + for (auto Val : Values) { + Type *Ty = Val->getType(); + + if (Ty->isFloatingPointTy()) { + if (!Ty->isDoubleTy()) + Val = Builder.CreateFPExt(Val, Builder.getDoubleTy()); + } else if (Ty->isIntegerTy()) { + if (Ty->getIntegerBitWidth() < 64) + Val = Builder.CreateSExt(Val, Builder.getInt64Ty()); + else + assert(Ty->getIntegerBitWidth() && + "Integer types larger 64 bit not supported"); + } else if (isa<PointerType>(Ty)) { + if (Ty->getPointerElementType() == Builder.getInt8Ty() && + Ty->getPointerAddressSpace() == 4) { + Val = Builder.CreateGEP(Val, Builder.getInt64(0)); + } else { + Val = Builder.CreatePtrToInt(Val, Builder.getInt64Ty()); + } + } else { + llvm_unreachable("Unknown type"); + } + + Ty = Val->getType(); + + if (Ty->isFloatingPointTy()) + FormatString += "%f"; + else if (Ty->isIntegerTy()) + FormatString += "%ld"; + else + FormatString += "%s"; + + ValuesToPrint.push_back(Val); + } + + return std::make_tuple(FormatString, ValuesToPrint); +} + +void RuntimeDebugBuilder::createCPUPrinterT(PollyIRBuilder &Builder, + ArrayRef<Value *> Values) { + + std::string FormatString; + std::vector<Value *> ValuesToPrint; + + std::tie(FormatString, ValuesToPrint) = + prepareValuesForPrinting(Builder, Values); + + createPrintF(Builder, FormatString, ValuesToPrint); + createFlush(Builder); +} + +void RuntimeDebugBuilder::createGPUPrinterT(PollyIRBuilder &Builder, + ArrayRef<Value *> Values) { std::string str; // Allocate print buffer (assuming 2*32 bit per element) @@ -169,14 +233,24 @@ Function *RuntimeDebugBuilder::getPrintF(PollyIRBuilder &Builder) { if (!F) { GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage; - FunctionType *Ty = - FunctionType::get(Builder.getInt32Ty(), Builder.getInt8PtrTy(), true); + FunctionType *Ty = FunctionType::get(Builder.getInt32Ty(), true); F = Function::Create(Ty, Linkage, Name, M); } return F; } +void RuntimeDebugBuilder::createPrintF(PollyIRBuilder &Builder, + std::string Format, + ArrayRef<Value *> Values) { + Value *FormatString = Builder.CreateGlobalStringPtr(Format); + std::vector<Value *> Arguments; + + Arguments.push_back(FormatString); + Arguments.insert(Arguments.end(), Values.begin(), Values.end()); + Builder.CreateCall(getPrintF(Builder), Arguments); +} + void RuntimeDebugBuilder::createFlush(PollyIRBuilder &Builder) { Module *M = Builder.GetInsertBlock()->getParent()->getParent(); const char *Name = "fflush"; @@ -197,30 +271,3 @@ void RuntimeDebugBuilder::createFlush(PollyIRBuilder &Builder) { // type to ensure that LLVM does not complain about mismatching types. Builder.CreateCall(F, Constant::getNullValue(F->arg_begin()->getType())); } - -void RuntimeDebugBuilder::createStrPrinter(PollyIRBuilder &Builder, - const std::string &String) { - Value *StringValue = Builder.CreateGlobalStringPtr(String); - Builder.CreateCall(getPrintF(Builder), StringValue); - - createFlush(Builder); -} - -void RuntimeDebugBuilder::createValuePrinter(PollyIRBuilder &Builder, - Value *V) { - const char *Format = nullptr; - - Type *Ty = V->getType(); - if (Ty->isIntegerTy()) - Format = "%ld"; - else if (Ty->isFloatingPointTy()) - Format = "%lf"; - else if (Ty->isPointerTy()) - Format = "%p"; - - assert(Format && Ty->getPrimitiveSizeInBits() <= 64 && "Bad type to print."); - - Value *FormatString = Builder.CreateGlobalStringPtr(Format); - Builder.CreateCall(getPrintF(Builder), {FormatString, V}); - createFlush(Builder); -} diff --git a/polly/test/Isl/CodeGen/RuntimeDebugBuilder/combine_different_values.c b/polly/test/Isl/CodeGen/RuntimeDebugBuilder/combine_different_values.c new file mode 100644 index 00000000000..c91098706d5 --- /dev/null +++ b/polly/test/Isl/CodeGen/RuntimeDebugBuilder/combine_different_values.c @@ -0,0 +1,23 @@ +#define N 10 +void foo(float A[restrict], double B[restrict], char C[restrict], + int D[restrict], long E[restrict]) { + for (long i = 0; i < N; i++) + A[i] += B[i] + C[i] + D[i] + E[i]; +} + +int main() { + float A[N]; + double B[N]; + char C[N]; + int D[N]; + long E[N]; + + for (long i = 0; i < N; i++) { + __sync_synchronize(); + A[i] = B[i] = C[i] = D[i] = E[i] = 42; + } + + foo(A, B, C, D, E); + + return A[8]; +} diff --git a/polly/test/Isl/CodeGen/RuntimeDebugBuilder/combine_different_values.ll b/polly/test/Isl/CodeGen/RuntimeDebugBuilder/combine_different_values.ll new file mode 100644 index 00000000000..d6a8d47e359 --- /dev/null +++ b/polly/test/Isl/CodeGen/RuntimeDebugBuilder/combine_different_values.ll @@ -0,0 +1,179 @@ +; RUN: opt %loadPolly -polly-codegen -S -polly-detect-unprofitable \ +; RUN: -polly-no-early-exit -polly-codegen-add-debug-printing \ +; RUN: -polly-ignore-aliasing < %s | FileCheck %s + +; #define N 10 +; void foo(float A[restrict], double B[restrict], char C[restrict], +; int D[restrict], long E[restrict]) { +; for (long i = 0; i < N; i++) +; A[i] += B[i] + C[i] + D[i] + E[i]; +; } +; +; int main() { +; float A[N]; +; double B[N]; +; char C[N]; +; int D[N]; +; long E[N]; +; +; for (long i = 0; i < N; i++) { +; __sync_synchronize(); +; A[i] = B[i] = C[i] = D[i] = E[i] = 42; +; } +; +; foo(A, B, C, D, E); +; +; return A[8]; +; } + +; CHECK: @0 = private unnamed_addr addrspace(4) constant [11 x i8] c"Load from \00" +; CHECK: @1 = private unnamed_addr addrspace(4) constant [3 x i8] c": \00" +; CHECK: @2 = private unnamed_addr addrspace(4) constant [2 x i8] c"\0A\00" +; CHECK: @3 = private unnamed_addr constant [12 x i8] c"%s%ld%s%f%s\00" +; CHECK: @4 = private unnamed_addr addrspace(4) constant [11 x i8] c"Load from \00" +; CHECK: @5 = private unnamed_addr addrspace(4) constant [3 x i8] c": \00" +; CHECK: @6 = private unnamed_addr addrspace(4) constant [2 x i8] c"\0A\00" +; CHECK: @7 = private unnamed_addr constant [13 x i8] c"%s%ld%s%ld%s\00" +; CHECK: @8 = private unnamed_addr addrspace(4) constant [11 x i8] c"Load from \00" +; CHECK: @9 = private unnamed_addr addrspace(4) constant [3 x i8] c": \00" +; CHECK: @10 = private unnamed_addr addrspace(4) constant [2 x i8] c"\0A\00" +; CHECK: @11 = private unnamed_addr constant [13 x i8] c"%s%ld%s%ld%s\00" +; CHECK: @12 = private unnamed_addr addrspace(4) constant [11 x i8] c"Load from \00" +; CHECK: @13 = private unnamed_addr addrspace(4) constant [3 x i8] c": \00" +; CHECK: @14 = private unnamed_addr addrspace(4) constant [2 x i8] c"\0A\00" +; CHECK: @15 = private unnamed_addr constant [13 x i8] c"%s%ld%s%ld%s\00" +; CHECK: @16 = private unnamed_addr addrspace(4) constant [11 x i8] c"Load from \00" +; CHECK: @17 = private unnamed_addr addrspace(4) constant [3 x i8] c": \00" +; CHECK: @18 = private unnamed_addr addrspace(4) constant [2 x i8] c"\0A\00" +; CHECK: @19 = private unnamed_addr constant [12 x i8] c"%s%ld%s%f%s\00" +; CHECK: @20 = private unnamed_addr addrspace(4) constant [11 x i8] c"Store to \00" +; CHECK: @21 = private unnamed_addr addrspace(4) constant [3 x i8] c": \00" +; CHECK: @22 = private unnamed_addr addrspace(4) constant [2 x i8] c"\0A\00" +; CHECK: @23 = private unnamed_addr constant [12 x i8] c"%s%ld%s%f%s\00" + +; CHECK: %0 = ptrtoint double* %scevgep to i64 +; CHECK: %1 = call i32 (...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @3, i32 0, i32 0), i8 addrspace(4)* getelementptr inbounds ([11 x i8], [11 x i8] addrspace(4)* @0, i32 0, i32 0), i64 %0, i8 addrspace(4)* getelementptr inbounds ([3 x i8], [3 x i8] addrspace(4)* @1, i32 0, i32 0), double %tmp3_p_scalar_, i8 addrspace(4)* getelementptr inbounds ([2 x i8], [2 x i8] addrspace(4)* @2, i32 0, i32 0)) +; CHECK: %2 = call i32 @fflush(i8* null) +; CHECK: %scevgep1 = getelementptr i8, i8* %C, i64 %polly.indvar +; CHECK: %tmp5_p_scalar_ = load i8, i8* %scevgep1, align 1, !alias.scope !4, !noalias !7 +; CHECK: %3 = ptrtoint i8* %scevgep1 to i64 +; CHECK: %4 = sext i8 %tmp5_p_scalar_ to i64 +; CHECK: %5 = call i32 (...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @7, i32 0, i32 0), i8 addrspace(4)* getelementptr inbounds ([11 x i8], [11 x i8] addrspace(4)* @4, i32 0, i32 0), i64 %3, i8 addrspace(4)* getelementptr inbounds ([3 x i8], [3 x i8] addrspace(4)* @5, i32 0, i32 0), i64 %4, i8 addrspace(4)* getelementptr inbounds ([2 x i8], [2 x i8] addrspace(4)* @6, i32 0, i32 0)) +; CHECK: %6 = call i32 @fflush(i8* null) +; CHECK: %p_tmp6 = sitofp i8 %tmp5_p_scalar_ to double +; CHECK: %p_tmp7 = fadd double %tmp3_p_scalar_, %p_tmp6 +; CHECK: %scevgep2 = getelementptr i32, i32* %D, i64 %polly.indvar +; CHECK: %tmp9_p_scalar_ = load i32, i32* %scevgep2, align 4, !alias.scope !5, !noalias !8 +; CHECK: %7 = ptrtoint i32* %scevgep2 to i64 +; CHECK: %8 = sext i32 %tmp9_p_scalar_ to i64 +; CHECK: %9 = call i32 (...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @11, i32 0, i32 0), i8 addrspace(4)* getelementptr inbounds ([11 x i8], [11 x i8] addrspace(4)* @8, i32 0, i32 0), i64 %7, i8 addrspace(4)* getelementptr inbounds ([3 x i8], [3 x i8] addrspace(4)* @9, i32 0, i32 0), i64 %8, i8 addrspace(4)* getelementptr inbounds ([2 x i8], [2 x i8] addrspace(4)* @10, i32 0, i32 0)) +; CHECK: %10 = call i32 @fflush(i8* null) +; CHECK: %p_tmp10 = sitofp i32 %tmp9_p_scalar_ to double +; CHECK: %p_tmp11 = fadd double %p_tmp7, %p_tmp10 +; CHECK: %scevgep3 = getelementptr i64, i64* %E, i64 %polly.indvar +; CHECK: %tmp13_p_scalar_ = load i64, i64* %scevgep3, align 8, !alias.scope !3, !noalias !9 +; CHECK: %11 = ptrtoint i64* %scevgep3 to i64 +; CHECK: %12 = call i32 (...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @15, i32 0, i32 0), i8 addrspace(4)* getelementptr inbounds ([11 x i8], [11 x i8] addrspace(4)* @12, i32 0, i32 0), i64 %11, i8 addrspace(4)* getelementptr inbounds ([3 x i8], [3 x i8] addrspace(4)* @13, i32 0, i32 0), i64 %tmp13_p_scalar_, i8 addrspace(4)* getelementptr inbounds ([2 x i8], [2 x i8] addrspace(4)* @14, i32 0, i32 0)) +; CHECK: %13 = call i32 @fflush(i8* null) +; CHECK: %p_tmp14 = sitofp i64 %tmp13_p_scalar_ to double +; CHECK: %p_tmp15 = fadd double %p_tmp11, %p_tmp14 +; CHECK: %scevgep4 = getelementptr float, float* %A, i64 %polly.indvar +; CHECK: %tmp17_p_scalar_ = load float, float* %scevgep4, align 4, !alias.scope !6, !noalias !10 +; CHECK: %14 = ptrtoint float* %scevgep4 to i64 +; CHECK: %15 = fpext float %tmp17_p_scalar_ to double +; CHECK: %16 = call i32 (...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @19, i32 0, i32 0), i8 addrspace(4)* getelementptr inbounds ([11 x i8], [11 x i8] addrspace(4)* @16, i32 0, i32 0), i64 %14, i8 addrspace(4)* getelementptr inbounds ([3 x i8], [3 x i8] addrspace(4)* @17, i32 0, i32 0), double %15, i8 addrspace(4)* getelementptr inbounds ([2 x i8], [2 x i8] addrspace(4)* @18, i32 0, i32 0)) +; CHECK: %17 = call i32 @fflush(i8* null) +; CHECK: %p_tmp18 = fpext float %tmp17_p_scalar_ to double +; CHECK: %p_tmp19 = fadd double %p_tmp18, %p_tmp15 +; CHECK: %p_tmp20 = fptrunc double %p_tmp19 to float +; CHECK: %18 = ptrtoint float* %scevgep4 to i64 +; CHECK: %19 = fpext float %p_tmp20 to double +; CHECK: %20 = call i32 (...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @23, i32 0, i32 0), i8 addrspace(4)* getelementptr inbounds ([11 x i8], [11 x i8] addrspace(4)* @20, i32 0, i32 0), i64 %18, i8 addrspace(4)* getelementptr inbounds ([3 x i8], [3 x i8] addrspace(4)* @21, i32 0, i32 0), double %19, i8 addrspace(4)* getelementptr inbounds ([2 x i8], [2 x i8] addrspace(4)* @22, i32 0, i32 0)) +; CHECK: %21 = call i32 @fflush(i8* null) + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +define void @foo(float* noalias %A, double* noalias %B, i8* noalias %C, i32* noalias %D, i64* noalias %E) { +bb: + br label %bb1 + +bb1: ; preds = %bb21, %bb + %i.0 = phi i64 [ 0, %bb ], [ %tmp22, %bb21 ] + %exitcond = icmp ne i64 %i.0, 10 + br i1 %exitcond, label %bb2, label %bb23 + +bb2: ; preds = %bb1 + %tmp = getelementptr inbounds double, double* %B, i64 %i.0 + %tmp3 = load double, double* %tmp, align 8 + %tmp4 = getelementptr inbounds i8, i8* %C, i64 %i.0 + %tmp5 = load i8, i8* %tmp4, align 1 + %tmp6 = sitofp i8 %tmp5 to double + %tmp7 = fadd double %tmp3, %tmp6 + %tmp8 = getelementptr inbounds i32, i32* %D, i64 %i.0 + %tmp9 = load i32, i32* %tmp8, align 4 + %tmp10 = sitofp i32 %tmp9 to double + %tmp11 = fadd double %tmp7, %tmp10 + %tmp12 = getelementptr inbounds i64, i64* %E, i64 %i.0 + %tmp13 = load i64, i64* %tmp12, align 8 + %tmp14 = sitofp i64 %tmp13 to double + %tmp15 = fadd double %tmp11, %tmp14 + %tmp16 = getelementptr inbounds float, float* %A, i64 %i.0 + %tmp17 = load float, float* %tmp16, align 4 + %tmp18 = fpext float %tmp17 to double + %tmp19 = fadd double %tmp18, %tmp15 + %tmp20 = fptrunc double %tmp19 to float + store float %tmp20, float* %tmp16, align 4 + br label %bb21 + +bb21: ; preds = %bb2 + %tmp22 = add nsw i64 %i.0, 1 + br label %bb1 + +bb23: ; preds = %bb1 + ret void +} + +define i32 @main() { +bb: + %A = alloca [10 x float], align 16 + %B = alloca [10 x double], align 16 + %C = alloca [10 x i8], align 1 + %D = alloca [10 x i32], align 16 + %E = alloca [10 x i64], align 16 + br label %bb1 + +bb1: ; preds = %bb7, %bb + %i.0 = phi i64 [ 0, %bb ], [ %tmp8, %bb7 ] + %exitcond = icmp ne i64 %i.0, 10 + br i1 %exitcond, label %bb2, label %bb9 + +bb2: ; preds = %bb1 + fence seq_cst + %tmp = getelementptr inbounds [10 x i64], [10 x i64]* %E, i64 0, i64 %i.0 + store i64 42, i64* %tmp, align 8 + %tmp3 = getelementptr inbounds [10 x i32], [10 x i32]* %D, i64 0, i64 %i.0 + store i32 42, i32* %tmp3, align 4 + %tmp4 = getelementptr inbounds [10 x i8], [10 x i8]* %C, i64 0, i64 %i.0 + store i8 42, i8* %tmp4, align 1 + %tmp5 = getelementptr inbounds [10 x double], [10 x double]* %B, i64 0, i64 %i.0 + store double 4.200000e+01, double* %tmp5, align 8 + %tmp6 = getelementptr inbounds [10 x float], [10 x float]* %A, i64 0, i64 %i.0 + store float 4.200000e+01, float* %tmp6, align 4 + br label %bb7 + +bb7: ; preds = %bb2 + %tmp8 = add nsw i64 %i.0, 1 + br label %bb1 + +bb9: ; preds = %bb1 + %tmp10 = getelementptr inbounds [10 x float], [10 x float]* %A, i64 0, i64 0 + %tmp11 = getelementptr inbounds [10 x double], [10 x double]* %B, i64 0, i64 0 + %tmp12 = getelementptr inbounds [10 x i8], [10 x i8]* %C, i64 0, i64 0 + %tmp13 = getelementptr inbounds [10 x i32], [10 x i32]* %D, i64 0, i64 0 + %tmp14 = getelementptr inbounds [10 x i64], [10 x i64]* %E, i64 0, i64 0 + call void @foo(float* %tmp10, double* %tmp11, i8* %tmp12, i32* %tmp13, i64* %tmp14) + %tmp15 = getelementptr inbounds [10 x float], [10 x float]* %A, i64 0, i64 8 + %tmp16 = load float, float* %tmp15, align 16 + %tmp17 = fptosi float %tmp16 to i32 + ret i32 %tmp17 +} |

