Index: llvm/lib/Analysis/Loads.cpp =================================================================== --- llvm/lib/Analysis/Loads.cpp +++ llvm/lib/Analysis/Loads.cpp @@ -29,9 +29,7 @@ static bool isAligned(const Value *Base, const APInt &Offset, Align Alignment, const DataLayout &DL) { Align BA = Base->getPointerAlignment(DL); - const APInt APAlign(Offset.getBitWidth(), Alignment.value()); - assert(APAlign.isPowerOf2() && "must be a power of 2!"); - return BA >= Alignment && !(Offset & (APAlign - 1)); + return BA >= Alignment && Offset.isAligned(BA); } /// Test if V is always a pointer to allocated and suitably aligned memory for Index: llvm/test/Transforms/ArgumentPromotion/load-alignment-value-overflows-addrspace-size.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/ArgumentPromotion/load-alignment-value-overflows-addrspace-size.ll @@ -0,0 +1,137 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 +; RUN: opt -S -passes=argpromotion < %s | FileCheck %s +target datalayout = "e-p:64:64-p5:32:32-p6:128:128:128:128" + +; Maximum alignment value of the load in a 64-bit address space +; exceeds the bitwidth of the definition address space. +define void @entry0() { +; CHECK-LABEL: define void @entry0() { +; CHECK-NEXT: bb: +; CHECK-NEXT: call void @call_load_maxalign_alloca_16() +; CHECK-NEXT: ret void +; +bb: + call void @call_load_maxalign_alloca_16() + ret void +} + +define internal void @call_load_maxalign_alloca_16() { +; CHECK-LABEL: define internal void @call_load_maxalign_alloca_16() { +; CHECK-NEXT: bb: +; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [13 x i16], align 16, addrspace(5) +; CHECK-NEXT: [[ADDRSPACECAST:%.*]] = addrspacecast ptr addrspace(5) [[ALLOCA]] to ptr +; CHECK-NEXT: call void @load_maxalign0(ptr [[ADDRSPACECAST]]) +; CHECK-NEXT: ret void +; +bb: + %alloca = alloca [13 x i16], align 16, addrspace(5) + %addrspacecast = addrspacecast ptr addrspace(5) %alloca to ptr + call void @load_maxalign0(ptr %addrspacecast) + ret void +} + +define internal void @load_maxalign0(ptr %arg) { +; CHECK-LABEL: define internal void @load_maxalign0 +; CHECK-SAME: (ptr [[ARG:%.*]]) { +; CHECK-NEXT: bb: +; CHECK-NEXT: br label [[BB1:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[ARG]], align 4294967296 +; CHECK-NEXT: ret void +; +bb: + br label %bb1 + +bb1: ; preds = %bb + %load = load i32, ptr %arg, align 4294967296 + ret void +} + +; Make sure the early exit alignment check isn't hiding the offset +; overflow. +define void @entry1() { +; CHECK-LABEL: define void @entry1() { +; CHECK-NEXT: bb: +; CHECK-NEXT: call void @call_load_maxalign_alloca_maxalign() +; CHECK-NEXT: ret void +; +bb: + call void @call_load_maxalign_alloca_maxalign() + ret void +} + +define internal void @call_load_maxalign_alloca_maxalign() { +; CHECK-LABEL: define internal void @call_load_maxalign_alloca_maxalign() { +; CHECK-NEXT: bb: +; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [13 x i16], align 4294967296, addrspace(5) +; CHECK-NEXT: [[ADDRSPACECAST:%.*]] = addrspacecast ptr addrspace(5) [[ALLOCA]] to ptr +; CHECK-NEXT: [[ADDRSPACECAST_VAL:%.*]] = load i32, ptr [[ADDRSPACECAST]], align 4294967296 +; CHECK-NEXT: call void @load_maxalign1(i32 [[ADDRSPACECAST_VAL]]) +; CHECK-NEXT: ret void +; +bb: + %alloca = alloca [13 x i16], align 4294967296, addrspace(5) + %addrspacecast = addrspacecast ptr addrspace(5) %alloca to ptr + call void @load_maxalign1(ptr %addrspacecast) + ret void +} + +define internal void @load_maxalign1(ptr %arg) { +; CHECK-LABEL: define internal void @load_maxalign1 +; CHECK-SAME: (i32 [[ARG_0_VAL:%.*]]) { +; CHECK-NEXT: bb: +; CHECK-NEXT: br label [[BB1:%.*]] +; CHECK: bb1: +; CHECK-NEXT: ret void +; +bb: + br label %bb1 + +bb1: ; preds = %bb + %load = load i32, ptr %arg, align 4294967296 + ret void +} + +; Alignment value exceeds pointer size, more than 1 past the end +define void @entry2() { +; CHECK-LABEL: define void @entry2() { +; CHECK-NEXT: bb: +; CHECK-NEXT: call void @call_load_maxalign_alloca_ptr128() +; CHECK-NEXT: ret void +; +bb: + call void @call_load_maxalign_alloca_ptr128() + ret void +} + +define internal void @call_load_maxalign_alloca_ptr128() { +; CHECK-LABEL: define internal void @call_load_maxalign_alloca_ptr128() { +; CHECK-NEXT: bb: +; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [13 x i16], align 4294967296, addrspace(6) +; CHECK-NEXT: [[ADDRSPACECAST:%.*]] = addrspacecast ptr addrspace(6) [[ALLOCA]] to ptr +; CHECK-NEXT: [[ADDRSPACECAST_VAL:%.*]] = load i32, ptr [[ADDRSPACECAST]], align 4294967296 +; CHECK-NEXT: call void @load_maxalign2(i32 [[ADDRSPACECAST_VAL]]) +; CHECK-NEXT: ret void +; +bb: + %alloca = alloca [13 x i16], align 4294967296, addrspace(6) + %addrspacecast = addrspacecast ptr addrspace(6) %alloca to ptr + call void @load_maxalign2(ptr %addrspacecast) + ret void +} + +define internal void @load_maxalign2(ptr %arg) { +; CHECK-LABEL: define internal void @load_maxalign2 +; CHECK-SAME: (i32 [[ARG_0_VAL:%.*]]) { +; CHECK-NEXT: bb: +; CHECK-NEXT: br label [[BB1:%.*]] +; CHECK: bb1: +; CHECK-NEXT: ret void +; +bb: + br label %bb1 + +bb1: ; preds = %bb + %load = load i32, ptr %arg, align 4294967296 + ret void +}