Index: llvm/trunk/lib/Target/PowerPC/PPCLoopPreIncPrep.cpp =================================================================== --- llvm/trunk/lib/Target/PowerPC/PPCLoopPreIncPrep.cpp +++ llvm/trunk/lib/Target/PowerPC/PPCLoopPreIncPrep.cpp @@ -294,6 +294,19 @@ if (const SCEVAddRecExpr *LARSCEV = dyn_cast(LSCEV)) { if (LARSCEV->getLoop() != L) continue; + // See getPreIndexedAddressParts, the displacement for LDU/STDU has to + // be 4's multiple (DS-form). For i64 loads/stores when the displacement + // fits in a 16-bit signed field but isn't a multiple of 4, it will be + // useless and possible to break some original well-form addressing mode + // to make this pre-inc prep for it. + if (PtrValue->getType()->getPointerElementType()->isIntegerTy(64)) { + if (const SCEVConstant *StepConst = + dyn_cast(LARSCEV->getStepRecurrence(*SE))) { + const APInt &ConstInt = StepConst->getValue()->getValue(); + if (ConstInt.isSignedIntN(16) && ConstInt.srem(4) != 0) + continue; + } + } } else { continue; } Index: llvm/trunk/test/CodeGen/PowerPC/preincprep-i64-check.ll =================================================================== --- llvm/trunk/test/CodeGen/PowerPC/preincprep-i64-check.ll +++ llvm/trunk/test/CodeGen/PowerPC/preincprep-i64-check.ll @@ -0,0 +1,124 @@ +; RUN: llc < %s -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr9 -verify-machineinstrs | FileCheck %s +; RUN: llc < %s -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr9 -verify-machineinstrs | FileCheck %s +; RUN: llc < %s -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr8 -verify-machineinstrs | FileCheck %s +; RUN: llc < %s -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr8 -verify-machineinstrs | FileCheck %s + +; Verify pre-inc preparation pass doesn't prepare pre-inc for i64 load/store +; when the stride doesn't conform LDU/STDU DS-form requirement. + +@result = local_unnamed_addr global i64 0, align 8 + +define i64 @test_preinc_i64_ld(i8* nocapture readonly, i64) local_unnamed_addr { + %3 = icmp eq i64 %1, 0 + br i1 %3, label %4, label %6 + +;