Index: lib/CodeGen/CGBlocks.cpp =================================================================== --- lib/CodeGen/CGBlocks.cpp +++ lib/CodeGen/CGBlocks.cpp @@ -1303,6 +1303,20 @@ // Load the function. llvm::Value *Func = Builder.CreateAlignedLoad(FuncPtr, getPointerAlign()); + // OpenCL v2.0 s6.12.5: + // Block variable declarations are implicitly qualified with const. + // Therefore all block variables must be initialized at declaration time and + // may not be reassigned. + // + // As such, load of block invoke function can be marked as invariant. This is + // to facilitate lowering of indirect function calls resulted from it to + // direct function calls since OpenCL does not require supporting of function + // pointer. + if (getLangOpts().OpenCL) + cast(Func)->setMetadata( + CGM.getModule().getMDKindID("invariant.load"), + llvm::MDNode::get(getLLVMContext(), None)); + const FunctionType *FuncTy = FnType->castAs(); const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeBlockFunctionCall(Args, FuncTy); Index: test/CodeGenOpenCL/blocks.cl =================================================================== --- test/CodeGenOpenCL/blocks.cl +++ test/CodeGenOpenCL/blocks.cl @@ -98,6 +98,19 @@ return blockArgFunc(^{return 42;}); } +// COMMON-LABEL: define {{.*}} @blockInLoopCondition +// COMMON: %[[INV:.*]] = getelementptr {{.*}}%block.literal, i32 0, i32 2 +// COMMON: load {{.*}}%[[INV]]{{.*}}, !invariant.load +void blockInLoopCondition(int* res, int tid, int multiplier) { + int (^kernelBlock)(int) = ^(int num) { + return num * multiplier; + }; + res[tid] = 39; + for(int i=0; i