Skip to content

Commit bc2a64f

Browse files
[InferAlignment] Enhance alignment propagation for and(ptrtoint, const) pattern. (#166935)
Fixes: #152797 alive2: https://alive2.llvm.org/ce/z/h8HYTo godbolt: https://godbolt.org/z/Mqzs9W8q4
1 parent cc92552 commit bc2a64f

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

llvm/lib/Transforms/Scalar/InferAlignment.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,20 @@
1212
//===----------------------------------------------------------------------===//
1313

1414
#include "llvm/Transforms/Scalar/InferAlignment.h"
15+
#include "llvm/ADT/APInt.h"
16+
#include "llvm/ADT/STLFunctionalExtras.h"
1517
#include "llvm/Analysis/AssumptionCache.h"
1618
#include "llvm/Analysis/ValueTracking.h"
19+
#include "llvm/IR/Instruction.h"
1720
#include "llvm/IR/Instructions.h"
1821
#include "llvm/IR/IntrinsicInst.h"
22+
#include "llvm/IR/PatternMatch.h"
1923
#include "llvm/Support/KnownBits.h"
2024
#include "llvm/Transforms/Scalar.h"
2125
#include "llvm/Transforms/Utils/Local.h"
2226

2327
using namespace llvm;
28+
using namespace llvm::PatternMatch;
2429

2530
static bool tryToImproveAlign(
2631
const DataLayout &DL, Instruction *I,
@@ -37,6 +42,16 @@ static bool tryToImproveAlign(
3742
}
3843
}
3944

45+
Value *PtrOp;
46+
const APInt *Const;
47+
if (match(I, m_And(m_PtrToIntOrAddr(m_Value(PtrOp)), m_APInt(Const)))) {
48+
Align ActualAlign = Fn(PtrOp, Align(1), Align(1));
49+
if (Const->ult(ActualAlign.value())) {
50+
I->replaceAllUsesWith(Constant::getNullValue(I->getType()));
51+
return true;
52+
}
53+
}
54+
4055
IntrinsicInst *II = dyn_cast<IntrinsicInst>(I);
4156
if (!II)
4257
return false;
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
2+
; RUN: opt < %s -passes=infer-alignment -S | FileCheck %s
3+
4+
define i64 @base(ptr %ptr) {
5+
; CHECK-LABEL: define i64 @base(
6+
; CHECK-SAME: ptr [[PTR:%.*]]) {
7+
; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[PTR]], align 4
8+
; CHECK-NEXT: [[V3:%.*]] = ptrtoint ptr [[PTR]] to i64
9+
; CHECK-NEXT: [[V5:%.*]] = and i64 [[V3]], 2
10+
; CHECK-NEXT: ret i64 0
11+
;
12+
%v1 = load i32, ptr %ptr, align 4
13+
%v3 = ptrtoint ptr %ptr to i64
14+
%v5 = and i64 %v3, 2
15+
ret i64 %v5
16+
}
17+
18+
define i64 @best_alignment(ptr %ptr) {
19+
; CHECK-LABEL: define i64 @best_alignment(
20+
; CHECK-SAME: ptr [[PTR:%.*]]) {
21+
; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[PTR]], align 8
22+
; CHECK-NEXT: [[V2:%.*]] = load i32, ptr [[PTR]], align 16
23+
; CHECK-NEXT: [[V3:%.*]] = ptrtoint ptr [[PTR]] to i64
24+
; CHECK-NEXT: [[V5:%.*]] = and i64 [[V3]], 15
25+
; CHECK-NEXT: ret i64 0
26+
;
27+
%v1 = load i32, ptr %ptr, align 8
28+
%v2 = load i32, ptr %ptr, align 16
29+
%v3 = ptrtoint ptr %ptr to i64
30+
%v5 = and i64 %v3, 15
31+
ret i64 %v5
32+
}
33+
34+
declare void @func()
35+
36+
define i64 @negative_test(ptr %ptr) {
37+
; CHECK-LABEL: define i64 @negative_test(
38+
; CHECK-SAME: ptr [[PTR:%.*]]) {
39+
; CHECK-NEXT: [[V3:%.*]] = ptrtoint ptr [[PTR]] to i64
40+
; CHECK-NEXT: [[V5:%.*]] = and i64 [[V3]], 2
41+
; CHECK-NEXT: call void @func()
42+
; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[PTR]], align 4
43+
; CHECK-NEXT: ret i64 [[V5]]
44+
;
45+
%v3 = ptrtoint ptr %ptr to i64
46+
%v5 = and i64 %v3, 2
47+
call void @func()
48+
%v1 = load i32, ptr %ptr, align 4
49+
ret i64 %v5
50+
}
51+
52+
define i64 @ptrtoaddr(ptr %ptr) {
53+
; CHECK-LABEL: define i64 @ptrtoaddr(
54+
; CHECK-SAME: ptr [[PTR:%.*]]) {
55+
; CHECK-NEXT: [[V3:%.*]] = ptrtoaddr ptr [[PTR]] to i64
56+
; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[PTR]], align 4
57+
; CHECK-NEXT: [[V5:%.*]] = and i64 [[V3]], 2
58+
; CHECK-NEXT: ret i64 0
59+
;
60+
%v3 = ptrtoaddr ptr %ptr to i64
61+
%v1 = load i32, ptr %ptr, align 4
62+
%v5 = and i64 %v3, 2
63+
ret i64 %v5
64+
}

0 commit comments

Comments
 (0)