diff --git a/lib/Transforms/Scalar/ConstantHoisting.cpp b/lib/Transforms/Scalar/ConstantHoisting.cpp index 9b7ed816ad9..af0450729a7 100644 --- a/lib/Transforms/Scalar/ConstantHoisting.cpp +++ b/lib/Transforms/Scalar/ConstantHoisting.cpp @@ -207,7 +207,16 @@ bool ConstantHoisting::runOnFunction(Function &Fn) { /// \brief Find the constant materialization insertion point. Instruction *ConstantHoisting::findMatInsertPt(Instruction *Inst, unsigned Idx) const { - // The simple and common case. + // If the operand is a cast instruction, then we have to materialize the + // constant before the cast instruction. + if (Idx != ~0U) { + Value *Opnd = Inst->getOperand(Idx); + if (auto CastInst = dyn_cast(Opnd)) + if (CastInst->isCast()) + return CastInst; + } + + // The simple and common case. This also includes constant expressions. if (!isa(Inst) && !isa(Inst)) return Inst; @@ -229,7 +238,7 @@ findConstantInsertionPoint(const ConstantInfo &ConstInfo) const { SmallPtrSet BBs; for (auto const &RCI : ConstInfo.RebasedConstants) for (auto const &U : RCI.Uses) - BBs.insert(U.Inst->getParent()); + BBs.insert(findMatInsertPt(U.Inst, U.OpndIdx)->getParent()); if (BBs.count(Entry)) return &Entry->front(); diff --git a/test/Transforms/ConstantHoisting/X86/cast-inst.ll b/test/Transforms/ConstantHoisting/X86/cast-inst.ll new file mode 100644 index 00000000000..f490f4a3723 --- /dev/null +++ b/test/Transforms/ConstantHoisting/X86/cast-inst.ll @@ -0,0 +1,29 @@ +; RUN: opt -S -consthoist < %s | FileCheck %s + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.9.0" + +; Check if the materialization of the constant and the cast instruction are +; inserted in the correct order. +define i32 @cast_inst_test() { +; CHECK-LABEL: @cast_inst_test +; CHECK: %const = bitcast i64 4646526064 to i64 +; CHECK: %1 = inttoptr i64 %const to i32* +; CHECK: %v0 = load i32* %1, align 16 +; CHECK: %const_mat = add i64 %const, 16 +; CHECK-NEXT: %2 = inttoptr i64 %const_mat to i32* +; CHECK-NEXT: %v1 = load i32* %2, align 16 +; CHECK: %const_mat1 = add i64 %const, 32 +; CHECK-NEXT: %3 = inttoptr i64 %const_mat1 to i32* +; CHECK-NEXT: %v2 = load i32* %3, align 16 + %a0 = inttoptr i64 4646526064 to i32* + %v0 = load i32* %a0, align 16 + %a1 = inttoptr i64 4646526080 to i32* + %v1 = load i32* %a1, align 16 + %a2 = inttoptr i64 4646526096 to i32* + %v2 = load i32* %a2, align 16 + %r0 = add i32 %v0, %v1 + %r1 = add i32 %r0, %v2 + ret i32 %r1 +} +