diff --git a/llvm/lib/Transforms/Scalar/InferAlignment.cpp b/llvm/lib/Transforms/Scalar/InferAlignment.cpp index 39751c04eba08..c0a147ed78231 100644 --- a/llvm/lib/Transforms/Scalar/InferAlignment.cpp +++ b/llvm/lib/Transforms/Scalar/InferAlignment.cpp @@ -12,15 +12,20 @@ //===----------------------------------------------------------------------===// #include "llvm/Transforms/Scalar/InferAlignment.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/STLFunctionalExtras.h" #include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/ValueTracking.h" +#include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/PatternMatch.h" #include "llvm/Support/KnownBits.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/Local.h" using namespace llvm; +using namespace llvm::PatternMatch; static bool tryToImproveAlign( const DataLayout &DL, Instruction *I, @@ -37,6 +42,16 @@ static bool tryToImproveAlign( } } + Value *PtrOp; + const APInt *Const; + if (match(I, m_And(m_PtrToIntOrAddr(m_Value(PtrOp)), m_APInt(Const)))) { + Align ActualAlign = Fn(PtrOp, Align(1), Align(1)); + if (Const->ult(ActualAlign.value())) { + I->replaceAllUsesWith(Constant::getNullValue(I->getType())); + return true; + } + } + IntrinsicInst *II = dyn_cast(I); if (!II) return false; diff --git a/llvm/test/Transforms/InferAlignment/ptrtoint.ll b/llvm/test/Transforms/InferAlignment/ptrtoint.ll new file mode 100644 index 0000000000000..3eb1f95d9c026 --- /dev/null +++ b/llvm/test/Transforms/InferAlignment/ptrtoint.ll @@ -0,0 +1,64 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 +; RUN: opt < %s -passes=infer-alignment -S | FileCheck %s + +define i64 @base(ptr %ptr) { +; CHECK-LABEL: define i64 @base( +; CHECK-SAME: ptr [[PTR:%.*]]) { +; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[PTR]], align 4 +; CHECK-NEXT: [[V3:%.*]] = ptrtoint ptr [[PTR]] to i64 +; CHECK-NEXT: [[V5:%.*]] = and i64 [[V3]], 2 +; CHECK-NEXT: ret i64 0 +; + %v1 = load i32, ptr %ptr, align 4 + %v3 = ptrtoint ptr %ptr to i64 + %v5 = and i64 %v3, 2 + ret i64 %v5 +} + +define i64 @best_alignment(ptr %ptr) { +; CHECK-LABEL: define i64 @best_alignment( +; CHECK-SAME: ptr [[PTR:%.*]]) { +; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[PTR]], align 8 +; CHECK-NEXT: [[V2:%.*]] = load i32, ptr [[PTR]], align 16 +; CHECK-NEXT: [[V3:%.*]] = ptrtoint ptr [[PTR]] to i64 +; CHECK-NEXT: [[V5:%.*]] = and i64 [[V3]], 15 +; CHECK-NEXT: ret i64 0 +; + %v1 = load i32, ptr %ptr, align 8 + %v2 = load i32, ptr %ptr, align 16 + %v3 = ptrtoint ptr %ptr to i64 + %v5 = and i64 %v3, 15 + ret i64 %v5 +} + +declare void @func() + +define i64 @negative_test(ptr %ptr) { +; CHECK-LABEL: define i64 @negative_test( +; CHECK-SAME: ptr [[PTR:%.*]]) { +; CHECK-NEXT: [[V3:%.*]] = ptrtoint ptr [[PTR]] to i64 +; CHECK-NEXT: [[V5:%.*]] = and i64 [[V3]], 2 +; CHECK-NEXT: call void @func() +; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[PTR]], align 4 +; CHECK-NEXT: ret i64 [[V5]] +; + %v3 = ptrtoint ptr %ptr to i64 + %v5 = and i64 %v3, 2 + call void @func() + %v1 = load i32, ptr %ptr, align 4 + ret i64 %v5 +} + +define i64 @ptrtoaddr(ptr %ptr) { +; CHECK-LABEL: define i64 @ptrtoaddr( +; CHECK-SAME: ptr [[PTR:%.*]]) { +; CHECK-NEXT: [[V3:%.*]] = ptrtoaddr ptr [[PTR]] to i64 +; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[PTR]], align 4 +; CHECK-NEXT: [[V5:%.*]] = and i64 [[V3]], 2 +; CHECK-NEXT: ret i64 0 +; + %v3 = ptrtoaddr ptr %ptr to i64 + %v1 = load i32, ptr %ptr, align 4 + %v5 = and i64 %v3, 2 + ret i64 %v5 +}