Skip to content

Commit 71be514

Browse files
committed
[Clang][CodeGen] Emit llvm.ptrmask for align_up and align_down
Since PR's #69343 and #67166 we probably have enough support for `llvm.ptrmask` to make it preferable to the GEP stategy. Closes #71238
1 parent 422ffc5 commit 71be514

File tree

3 files changed

+58
-86
lines changed

3 files changed

+58
-86
lines changed

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19668,44 +19668,40 @@ RValue CodeGenFunction::EmitBuiltinIsAligned(const CallExpr *E) {
1966819668
/// Generate (x & ~(y-1)) to align down or ((x+(y-1)) & ~(y-1)) to align up.
1966919669
/// Note: For pointer types we can avoid ptrtoint/inttoptr pairs by using the
1967019670
/// llvm.ptrmask intrinsic (with a GEP before in the align_up case).
19671-
/// TODO: actually use ptrmask once most optimization passes know about it.
1967219671
RValue CodeGenFunction::EmitBuiltinAlignTo(const CallExpr *E, bool AlignUp) {
1967319672
BuiltinAlignArgs Args(E, *this);
19674-
llvm::Value *SrcAddr = Args.Src;
19675-
if (Args.Src->getType()->isPointerTy())
19676-
SrcAddr = Builder.CreatePtrToInt(Args.Src, Args.IntType, "intptr");
19677-
llvm::Value *SrcForMask = SrcAddr;
19673+
llvm::Value *SrcForMask = Args.Src;
1967819674
if (AlignUp) {
1967919675
// When aligning up we have to first add the mask to ensure we go over the
1968019676
// next alignment value and then align down to the next valid multiple.
1968119677
// By adding the mask, we ensure that align_up on an already aligned
1968219678
// value will not change the value.
19683-
SrcForMask = Builder.CreateAdd(SrcForMask, Args.Mask, "over_boundary");
19679+
if (Args.Src->getType()->isPointerTy()) {
19680+
if (getLangOpts().isSignedOverflowDefined())
19681+
SrcForMask =
19682+
Builder.CreateGEP(Int8Ty, SrcForMask, Args.Mask, "over_boundary");
19683+
else
19684+
SrcForMask = EmitCheckedInBoundsGEP(Int8Ty, SrcForMask, Args.Mask,
19685+
/*SignedIndices=*/true,
19686+
/*isSubtraction=*/false,
19687+
E->getExprLoc(), "over_boundary");
19688+
} else {
19689+
SrcForMask = Builder.CreateAdd(SrcForMask, Args.Mask, "over_boundary");
19690+
}
1968419691
}
1968519692
// Invert the mask to only clear the lower bits.
1968619693
llvm::Value *InvertedMask = Builder.CreateNot(Args.Mask, "inverted_mask");
19687-
llvm::Value *Result =
19688-
Builder.CreateAnd(SrcForMask, InvertedMask, "aligned_result");
19694+
llvm::Value *Result = nullptr;
1968919695
if (Args.Src->getType()->isPointerTy()) {
19690-
/// TODO: Use ptrmask instead of ptrtoint+gep once it is optimized well.
19691-
// Result = Builder.CreateIntrinsic(
19692-
// Intrinsic::ptrmask, {Args.SrcType, SrcForMask->getType(), Args.IntType},
19693-
// {SrcForMask, NegatedMask}, nullptr, "aligned_result");
19694-
Result->setName("aligned_intptr");
19695-
llvm::Value *Difference = Builder.CreateSub(Result, SrcAddr, "diff");
19696-
// The result must point to the same underlying allocation. This means we
19697-
// can use an inbounds GEP to enable better optimization.
19698-
if (getLangOpts().isSignedOverflowDefined())
19699-
Result =
19700-
Builder.CreateGEP(Int8Ty, Args.Src, Difference, "aligned_result");
19701-
else
19702-
Result = EmitCheckedInBoundsGEP(Int8Ty, Args.Src, Difference,
19703-
/*SignedIndices=*/true,
19704-
/*isSubtraction=*/!AlignUp,
19705-
E->getExprLoc(), "aligned_result");
19696+
Result = Builder.CreateIntrinsic(
19697+
Intrinsic::ptrmask, {Args.SrcType, Args.IntType},
19698+
{SrcForMask, InvertedMask}, nullptr, "aligned_result");
19699+
1970619700
// Emit an alignment assumption to ensure that the new alignment is
1970719701
// propagated to loads/stores, etc.
1970819702
emitAlignmentAssumption(Result, E, E->getExprLoc(), Args.Alignment);
19703+
} else {
19704+
Result = Builder.CreateAnd(SrcForMask, InvertedMask, "aligned_result");
1970919705
}
1971019706
assert(Result->getType() == Args.SrcType);
1971119707
return RValue::get(Result);

clang/test/CodeGen/builtin-align-array.c

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,16 @@ extern int func(char *c);
88
// CHECK-NEXT: entry:
99
// CHECK-NEXT: [[BUF:%.*]] = alloca [1024 x i8], align 16
1010
// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BUF]], i64 0, i64 44
11-
// CHECK-NEXT: [[INTPTR:%.*]] = ptrtoint ptr [[ARRAYIDX]] to i64
12-
// CHECK-NEXT: [[ALIGNED_INTPTR:%.*]] = and i64 [[INTPTR]], -16
13-
// CHECK-NEXT: [[DIFF:%.*]] = sub i64 [[ALIGNED_INTPTR]], [[INTPTR]]
14-
// CHECK-NEXT: [[ALIGNED_RESULT:%.*]] = getelementptr inbounds i8, ptr [[ARRAYIDX]], i64 [[DIFF]]
11+
// CHECK-NEXT: [[ALIGNED_RESULT:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[ARRAYIDX]], i64 -16)
1512
// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[ALIGNED_RESULT]], i64 16) ]
1613
// CHECK-NEXT: [[CALL:%.*]] = call i32 @func(ptr noundef [[ALIGNED_RESULT]])
1714
// CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BUF]], i64 0, i64 22
18-
// CHECK-NEXT: [[INTPTR2:%.*]] = ptrtoint ptr [[ARRAYIDX1]] to i64
19-
// CHECK-NEXT: [[OVER_BOUNDARY:%.*]] = add i64 [[INTPTR2]], 31
20-
// CHECK-NEXT: [[ALIGNED_INTPTR4:%.*]] = and i64 [[OVER_BOUNDARY]], -32
21-
// CHECK-NEXT: [[DIFF5:%.*]] = sub i64 [[ALIGNED_INTPTR4]], [[INTPTR2]]
22-
// CHECK-NEXT: [[ALIGNED_RESULT6:%.*]] = getelementptr inbounds i8, ptr [[ARRAYIDX1]], i64 [[DIFF5]]
23-
// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[ALIGNED_RESULT6]], i64 32) ]
24-
// CHECK-NEXT: [[CALL7:%.*]] = call i32 @func(ptr noundef [[ALIGNED_RESULT6]])
25-
// CHECK-NEXT: [[ARRAYIDX8:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BUF]], i64 0, i64 16
26-
// CHECK-NEXT: [[SRC_ADDR:%.*]] = ptrtoint ptr [[ARRAYIDX8]] to i64
15+
// CHECK-NEXT: [[OVER_BOUNDARY:%.*]] = getelementptr inbounds i8, ptr [[ARRAYIDX1]], i64 31
16+
// CHECK-NEXT: [[ALIGNED_RESULT2:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[OVER_BOUNDARY]], i64 -32)
17+
// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[ALIGNED_RESULT2]], i64 32) ]
18+
// CHECK-NEXT: [[CALL3:%.*]] = call i32 @func(ptr noundef [[ALIGNED_RESULT2]])
19+
// CHECK-NEXT: [[ARRAYIDX4:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BUF]], i64 0, i64 16
20+
// CHECK-NEXT: [[SRC_ADDR:%.*]] = ptrtoint ptr [[ARRAYIDX4]] to i64
2721
// CHECK-NEXT: [[SET_BITS:%.*]] = and i64 [[SRC_ADDR]], 63
2822
// CHECK-NEXT: [[IS_ALIGNED:%.*]] = icmp eq i64 [[SET_BITS]], 0
2923
// CHECK-NEXT: [[CONV:%.*]] = zext i1 [[IS_ALIGNED]] to i32
@@ -40,20 +34,14 @@ int test_array(void) {
4034
// CHECK-NEXT: entry:
4135
// CHECK-NEXT: [[BUF:%.*]] = alloca [1024 x i8], align 32
4236
// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BUF]], i64 0, i64 64
43-
// CHECK-NEXT: [[INTPTR:%.*]] = ptrtoint ptr [[ARRAYIDX]] to i64
44-
// CHECK-NEXT: [[ALIGNED_INTPTR:%.*]] = and i64 [[INTPTR]], -16
45-
// CHECK-NEXT: [[DIFF:%.*]] = sub i64 [[ALIGNED_INTPTR]], [[INTPTR]]
46-
// CHECK-NEXT: [[ALIGNED_RESULT:%.*]] = getelementptr inbounds i8, ptr [[ARRAYIDX]], i64 [[DIFF]]
37+
// CHECK-NEXT: [[ALIGNED_RESULT:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[ARRAYIDX]], i64 -16)
4738
// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[ALIGNED_RESULT]], i64 16) ]
4839
// CHECK-NEXT: [[CALL:%.*]] = call i32 @func(ptr noundef [[ALIGNED_RESULT]])
4940
// CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BUF]], i64 0, i64 32
50-
// CHECK-NEXT: [[INTPTR2:%.*]] = ptrtoint ptr [[ARRAYIDX1]] to i64
51-
// CHECK-NEXT: [[OVER_BOUNDARY:%.*]] = add i64 [[INTPTR2]], 31
52-
// CHECK-NEXT: [[ALIGNED_INTPTR4:%.*]] = and i64 [[OVER_BOUNDARY]], -32
53-
// CHECK-NEXT: [[DIFF5:%.*]] = sub i64 [[ALIGNED_INTPTR4]], [[INTPTR2]]
54-
// CHECK-NEXT: [[ALIGNED_RESULT6:%.*]] = getelementptr inbounds i8, ptr [[ARRAYIDX1]], i64 [[DIFF5]]
55-
// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[ALIGNED_RESULT6]], i64 32) ]
56-
// CHECK-NEXT: [[CALL7:%.*]] = call i32 @func(ptr noundef [[ALIGNED_RESULT6]])
41+
// CHECK-NEXT: [[OVER_BOUNDARY:%.*]] = getelementptr inbounds i8, ptr [[ARRAYIDX1]], i64 31
42+
// CHECK-NEXT: [[ALIGNED_RESULT2:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[OVER_BOUNDARY]], i64 -32)
43+
// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[ALIGNED_RESULT2]], i64 32) ]
44+
// CHECK-NEXT: [[CALL3:%.*]] = call i32 @func(ptr noundef [[ALIGNED_RESULT2]])
5745
// CHECK-NEXT: ret i32 1
5846
//
5947
int test_array_should_not_mask(void) {

clang/test/CodeGen/builtin-align.c

Lines changed: 26 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -71,38 +71,38 @@ TYPE get_type(void) {
7171
// CHECK-VOID_PTR-LABEL: define {{[^@]+}}@is_aligned
7272
// CHECK-VOID_PTR-SAME: (ptr noundef [[PTR:%.*]], i32 noundef [[ALIGN:%.*]]) #0
7373
// CHECK-VOID_PTR-NEXT: entry:
74-
// CHECK-VOID_PTR-NEXT: [[ALIGNMENT:%.*]] = zext i32 [[ALIGN]] to i64
74+
// CHECK-VOID_PTR-NEXT: [[ALIGNMENT:%.*]] = zext i32 [[ALIGN:%.*]] to i64
7575
// CHECK-VOID_PTR-NEXT: [[MASK:%.*]] = sub i64 [[ALIGNMENT]], 1
76-
// CHECK-VOID_PTR-NEXT: [[SRC_ADDR:%.*]] = ptrtoint ptr [[PTR]] to i64
76+
// CHECK-VOID_PTR-NEXT: [[SRC_ADDR:%.*]] = ptrtoint ptr [[PTR:%.*]] to i64
7777
// CHECK-VOID_PTR-NEXT: [[SET_BITS:%.*]] = and i64 [[SRC_ADDR]], [[MASK]]
7878
// CHECK-VOID_PTR-NEXT: [[IS_ALIGNED:%.*]] = icmp eq i64 [[SET_BITS]], 0
7979
// CHECK-VOID_PTR-NEXT: ret i1 [[IS_ALIGNED]]
8080
//
8181
// CHECK-FLOAT_PTR-LABEL: define {{[^@]+}}@is_aligned
8282
// CHECK-FLOAT_PTR-SAME: (ptr noundef [[PTR:%.*]], i32 noundef [[ALIGN:%.*]]) #0
8383
// CHECK-FLOAT_PTR-NEXT: entry:
84-
// CHECK-FLOAT_PTR-NEXT: [[ALIGNMENT:%.*]] = zext i32 [[ALIGN]] to i64
84+
// CHECK-FLOAT_PTR-NEXT: [[ALIGNMENT:%.*]] = zext i32 [[ALIGN:%.*]] to i64
8585
// CHECK-FLOAT_PTR-NEXT: [[MASK:%.*]] = sub i64 [[ALIGNMENT]], 1
86-
// CHECK-FLOAT_PTR-NEXT: [[SRC_ADDR:%.*]] = ptrtoint ptr [[PTR]] to i64
86+
// CHECK-FLOAT_PTR-NEXT: [[SRC_ADDR:%.*]] = ptrtoint ptr [[PTR:%.*]] to i64
8787
// CHECK-FLOAT_PTR-NEXT: [[SET_BITS:%.*]] = and i64 [[SRC_ADDR]], [[MASK]]
8888
// CHECK-FLOAT_PTR-NEXT: [[IS_ALIGNED:%.*]] = icmp eq i64 [[SET_BITS]], 0
8989
// CHECK-FLOAT_PTR-NEXT: ret i1 [[IS_ALIGNED]]
9090
//
9191
// CHECK-LONG-LABEL: define {{[^@]+}}@is_aligned
9292
// CHECK-LONG-SAME: (i64 noundef [[PTR:%.*]], i32 noundef [[ALIGN:%.*]]) #0
9393
// CHECK-LONG-NEXT: entry:
94-
// CHECK-LONG-NEXT: [[ALIGNMENT:%.*]] = zext i32 [[ALIGN]] to i64
94+
// CHECK-LONG-NEXT: [[ALIGNMENT:%.*]] = zext i32 [[ALIGN:%.*]] to i64
9595
// CHECK-LONG-NEXT: [[MASK:%.*]] = sub i64 [[ALIGNMENT]], 1
96-
// CHECK-LONG-NEXT: [[SET_BITS:%.*]] = and i64 [[PTR]], [[MASK]]
96+
// CHECK-LONG-NEXT: [[SET_BITS:%.*]] = and i64 [[PTR:%.*]], [[MASK]]
9797
// CHECK-LONG-NEXT: [[IS_ALIGNED:%.*]] = icmp eq i64 [[SET_BITS]], 0
9898
// CHECK-LONG-NEXT: ret i1 [[IS_ALIGNED]]
9999
//
100100
// CHECK-USHORT-LABEL: define {{[^@]+}}@is_aligned
101101
// CHECK-USHORT-SAME: (i16 noundef zeroext [[PTR:%.*]], i32 noundef [[ALIGN:%.*]]) #0
102102
// CHECK-USHORT-NEXT: entry:
103-
// CHECK-USHORT-NEXT: [[ALIGNMENT:%.*]] = trunc i32 [[ALIGN]] to i16
103+
// CHECK-USHORT-NEXT: [[ALIGNMENT:%.*]] = trunc i32 [[ALIGN:%.*]] to i16
104104
// CHECK-USHORT-NEXT: [[MASK:%.*]] = sub i16 [[ALIGNMENT]], 1
105-
// CHECK-USHORT-NEXT: [[SET_BITS:%.*]] = and i16 [[PTR]], [[MASK]]
105+
// CHECK-USHORT-NEXT: [[SET_BITS:%.*]] = and i16 [[PTR:%.*]], [[MASK]]
106106
// CHECK-USHORT-NEXT: [[IS_ALIGNED:%.*]] = icmp eq i16 [[SET_BITS]], 0
107107
// CHECK-USHORT-NEXT: ret i1 [[IS_ALIGNED]]
108108
//
@@ -114,47 +114,41 @@ _Bool is_aligned(TYPE ptr, unsigned align) {
114114
// CHECK-VOID_PTR-LABEL: define {{[^@]+}}@align_up
115115
// CHECK-VOID_PTR-SAME: (ptr noundef [[PTR:%.*]], i32 noundef [[ALIGN:%.*]]) #0
116116
// CHECK-VOID_PTR-NEXT: entry:
117-
// CHECK-VOID_PTR-NEXT: [[ALIGNMENT:%.*]] = zext i32 [[ALIGN]] to i64
117+
// CHECK-VOID_PTR-NEXT: [[ALIGNMENT:%.*]] = zext i32 [[ALIGN:%.*]] to i64
118118
// CHECK-VOID_PTR-NEXT: [[MASK:%.*]] = sub i64 [[ALIGNMENT]], 1
119-
// CHECK-VOID_PTR-NEXT: [[INTPTR:%.*]] = ptrtoint ptr [[PTR]] to i64
120-
// CHECK-VOID_PTR-NEXT: [[OVER_BOUNDARY:%.*]] = add i64 [[INTPTR]], [[MASK]]
119+
// CHECK-VOID_PTR-NEXT: [[OVER_BOUNDARY:%.*]] = getelementptr inbounds i8, ptr [[PTR:%.*]], i64 [[MASK]]
121120
// CHECK-VOID_PTR-NEXT: [[INVERTED_MASK:%.*]] = xor i64 [[MASK]], -1
122-
// CHECK-VOID_PTR-NEXT: [[ALIGNED_INTPTR:%.*]] = and i64 [[OVER_BOUNDARY]], [[INVERTED_MASK]]
123-
// CHECK-VOID_PTR-NEXT: [[DIFF:%.*]] = sub i64 [[ALIGNED_INTPTR]], [[INTPTR]]
124-
// CHECK-VOID_PTR-NEXT: [[ALIGNED_RESULT:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 [[DIFF]]
121+
// CHECK-VOID_PTR-NEXT: [[ALIGNED_RESULT:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[OVER_BOUNDARY]], i64 [[INVERTED_MASK]])
125122
// CHECK-VOID_PTR-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[ALIGNED_RESULT]], i64 [[ALIGNMENT]]) ]
126123
// CHECK-VOID_PTR-NEXT: ret ptr [[ALIGNED_RESULT]]
127124
//
128125
// CHECK-FLOAT_PTR-LABEL: define {{[^@]+}}@align_up
129126
// CHECK-FLOAT_PTR-SAME: (ptr noundef [[PTR:%.*]], i32 noundef [[ALIGN:%.*]]) #0
130127
// CHECK-FLOAT_PTR-NEXT: entry:
131-
// CHECK-FLOAT_PTR-NEXT: [[ALIGNMENT:%.*]] = zext i32 [[ALIGN]] to i64
128+
// CHECK-FLOAT_PTR-NEXT: [[ALIGNMENT:%.*]] = zext i32 [[ALIGN:%.*]] to i64
132129
// CHECK-FLOAT_PTR-NEXT: [[MASK:%.*]] = sub i64 [[ALIGNMENT]], 1
133-
// CHECK-FLOAT_PTR-NEXT: [[INTPTR:%.*]] = ptrtoint ptr [[PTR]] to i64
134-
// CHECK-FLOAT_PTR-NEXT: [[OVER_BOUNDARY:%.*]] = add i64 [[INTPTR]], [[MASK]]
130+
// CHECK-FLOAT_PTR-NEXT: [[OVER_BOUNDARY:%.*]] = getelementptr inbounds i8, ptr [[PTR:%.*]], i64 [[MASK]]
135131
// CHECK-FLOAT_PTR-NEXT: [[INVERTED_MASK:%.*]] = xor i64 [[MASK]], -1
136-
// CHECK-FLOAT_PTR-NEXT: [[ALIGNED_INTPTR:%.*]] = and i64 [[OVER_BOUNDARY]], [[INVERTED_MASK]]
137-
// CHECK-FLOAT_PTR-NEXT: [[DIFF:%.*]] = sub i64 [[ALIGNED_INTPTR]], [[INTPTR]]
138-
// CHECK-FLOAT_PTR-NEXT: [[ALIGNED_RESULT:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 [[DIFF]]
132+
// CHECK-FLOAT_PTR-NEXT: [[ALIGNED_RESULT:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[OVER_BOUNDARY]], i64 [[INVERTED_MASK]])
139133
// CHECK-FLOAT_PTR-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[ALIGNED_RESULT]], i64 [[ALIGNMENT]]) ]
140134
// CHECK-FLOAT_PTR-NEXT: ret ptr [[ALIGNED_RESULT]]
141135
//
142136
// CHECK-LONG-LABEL: define {{[^@]+}}@align_up
143137
// CHECK-LONG-SAME: (i64 noundef [[PTR:%.*]], i32 noundef [[ALIGN:%.*]]) #0
144138
// CHECK-LONG-NEXT: entry:
145-
// CHECK-LONG-NEXT: [[ALIGNMENT:%.*]] = zext i32 [[ALIGN]] to i64
139+
// CHECK-LONG-NEXT: [[ALIGNMENT:%.*]] = zext i32 [[ALIGN:%.*]] to i64
146140
// CHECK-LONG-NEXT: [[MASK:%.*]] = sub i64 [[ALIGNMENT]], 1
147-
// CHECK-LONG-NEXT: [[OVER_BOUNDARY:%.*]] = add i64 [[PTR]], [[MASK]]
141+
// CHECK-LONG-NEXT: [[OVER_BOUNDARY:%.*]] = add i64 [[PTR:%.*]], [[MASK]]
148142
// CHECK-LONG-NEXT: [[INVERTED_MASK:%.*]] = xor i64 [[MASK]], -1
149143
// CHECK-LONG-NEXT: [[ALIGNED_RESULT:%.*]] = and i64 [[OVER_BOUNDARY]], [[INVERTED_MASK]]
150144
// CHECK-LONG-NEXT: ret i64 [[ALIGNED_RESULT]]
151145
//
152146
// CHECK-USHORT-LABEL: define {{[^@]+}}@align_up
153147
// CHECK-USHORT-SAME: (i16 noundef zeroext [[PTR:%.*]], i32 noundef [[ALIGN:%.*]]) #0
154148
// CHECK-USHORT-NEXT: entry:
155-
// CHECK-USHORT-NEXT: [[ALIGNMENT:%.*]] = trunc i32 [[ALIGN]] to i16
149+
// CHECK-USHORT-NEXT: [[ALIGNMENT:%.*]] = trunc i32 [[ALIGN:%.*]] to i16
156150
// CHECK-USHORT-NEXT: [[MASK:%.*]] = sub i16 [[ALIGNMENT]], 1
157-
// CHECK-USHORT-NEXT: [[OVER_BOUNDARY:%.*]] = add i16 [[PTR]], [[MASK]]
151+
// CHECK-USHORT-NEXT: [[OVER_BOUNDARY:%.*]] = add i16 [[PTR:%.*]], [[MASK]]
158152
// CHECK-USHORT-NEXT: [[INVERTED_MASK:%.*]] = xor i16 [[MASK]], -1
159153
// CHECK-USHORT-NEXT: [[ALIGNED_RESULT:%.*]] = and i16 [[OVER_BOUNDARY]], [[INVERTED_MASK]]
160154
// CHECK-USHORT-NEXT: ret i16 [[ALIGNED_RESULT]]
@@ -167,45 +161,39 @@ TYPE align_up(TYPE ptr, unsigned align) {
167161
// CHECK-VOID_PTR-LABEL: define {{[^@]+}}@align_down
168162
// CHECK-VOID_PTR-SAME: (ptr noundef [[PTR:%.*]], i32 noundef [[ALIGN:%.*]]) #0
169163
// CHECK-VOID_PTR-NEXT: entry:
170-
// CHECK-VOID_PTR-NEXT: [[ALIGNMENT:%.*]] = zext i32 [[ALIGN]] to i64
164+
// CHECK-VOID_PTR-NEXT: [[ALIGNMENT:%.*]] = zext i32 [[ALIGN:%.*]] to i64
171165
// CHECK-VOID_PTR-NEXT: [[MASK:%.*]] = sub i64 [[ALIGNMENT]], 1
172-
// CHECK-VOID_PTR-NEXT: [[INTPTR:%.*]] = ptrtoint ptr [[PTR]] to i64
173166
// CHECK-VOID_PTR-NEXT: [[INVERTED_MASK:%.*]] = xor i64 [[MASK]], -1
174-
// CHECK-VOID_PTR-NEXT: [[ALIGNED_INTPTR:%.*]] = and i64 [[INTPTR]], [[INVERTED_MASK]]
175-
// CHECK-VOID_PTR-NEXT: [[DIFF:%.*]] = sub i64 [[ALIGNED_INTPTR]], [[INTPTR]]
176-
// CHECK-VOID_PTR-NEXT: [[ALIGNED_RESULT:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 [[DIFF]]
167+
// CHECK-VOID_PTR-NEXT: [[ALIGNED_RESULT:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[PTR:%.*]], i64 [[INVERTED_MASK]])
177168
// CHECK-VOID_PTR-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[ALIGNED_RESULT]], i64 [[ALIGNMENT]]) ]
178169
// CHECK-VOID_PTR-NEXT: ret ptr [[ALIGNED_RESULT]]
179170
//
180171
// CHECK-FLOAT_PTR-LABEL: define {{[^@]+}}@align_down
181172
// CHECK-FLOAT_PTR-SAME: (ptr noundef [[PTR:%.*]], i32 noundef [[ALIGN:%.*]]) #0
182173
// CHECK-FLOAT_PTR-NEXT: entry:
183-
// CHECK-FLOAT_PTR-NEXT: [[ALIGNMENT:%.*]] = zext i32 [[ALIGN]] to i64
174+
// CHECK-FLOAT_PTR-NEXT: [[ALIGNMENT:%.*]] = zext i32 [[ALIGN:%.*]] to i64
184175
// CHECK-FLOAT_PTR-NEXT: [[MASK:%.*]] = sub i64 [[ALIGNMENT]], 1
185-
// CHECK-FLOAT_PTR-NEXT: [[INTPTR:%.*]] = ptrtoint ptr [[PTR]] to i64
186176
// CHECK-FLOAT_PTR-NEXT: [[INVERTED_MASK:%.*]] = xor i64 [[MASK]], -1
187-
// CHECK-FLOAT_PTR-NEXT: [[ALIGNED_INTPTR:%.*]] = and i64 [[INTPTR]], [[INVERTED_MASK]]
188-
// CHECK-FLOAT_PTR-NEXT: [[DIFF:%.*]] = sub i64 [[ALIGNED_INTPTR]], [[INTPTR]]
189-
// CHECK-FLOAT_PTR-NEXT: [[ALIGNED_RESULT:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 [[DIFF]]
177+
// CHECK-FLOAT_PTR-NEXT: [[ALIGNED_RESULT:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[PTR:%.*]], i64 [[INVERTED_MASK]])
190178
// CHECK-FLOAT_PTR-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[ALIGNED_RESULT]], i64 [[ALIGNMENT]]) ]
191179
// CHECK-FLOAT_PTR-NEXT: ret ptr [[ALIGNED_RESULT]]
192180
//
193181
// CHECK-LONG-LABEL: define {{[^@]+}}@align_down
194182
// CHECK-LONG-SAME: (i64 noundef [[PTR:%.*]], i32 noundef [[ALIGN:%.*]]) #0
195183
// CHECK-LONG-NEXT: entry:
196-
// CHECK-LONG-NEXT: [[ALIGNMENT:%.*]] = zext i32 [[ALIGN]] to i64
184+
// CHECK-LONG-NEXT: [[ALIGNMENT:%.*]] = zext i32 [[ALIGN:%.*]] to i64
197185
// CHECK-LONG-NEXT: [[MASK:%.*]] = sub i64 [[ALIGNMENT]], 1
198186
// CHECK-LONG-NEXT: [[INVERTED_MASK:%.*]] = xor i64 [[MASK]], -1
199-
// CHECK-LONG-NEXT: [[ALIGNED_RESULT:%.*]] = and i64 [[PTR]], [[INVERTED_MASK]]
187+
// CHECK-LONG-NEXT: [[ALIGNED_RESULT:%.*]] = and i64 [[PTR:%.*]], [[INVERTED_MASK]]
200188
// CHECK-LONG-NEXT: ret i64 [[ALIGNED_RESULT]]
201189
//
202190
// CHECK-USHORT-LABEL: define {{[^@]+}}@align_down
203191
// CHECK-USHORT-SAME: (i16 noundef zeroext [[PTR:%.*]], i32 noundef [[ALIGN:%.*]]) #0
204192
// CHECK-USHORT-NEXT: entry:
205-
// CHECK-USHORT-NEXT: [[ALIGNMENT:%.*]] = trunc i32 [[ALIGN]] to i16
193+
// CHECK-USHORT-NEXT: [[ALIGNMENT:%.*]] = trunc i32 [[ALIGN:%.*]] to i16
206194
// CHECK-USHORT-NEXT: [[MASK:%.*]] = sub i16 [[ALIGNMENT]], 1
207195
// CHECK-USHORT-NEXT: [[INVERTED_MASK:%.*]] = xor i16 [[MASK]], -1
208-
// CHECK-USHORT-NEXT: [[ALIGNED_RESULT:%.*]] = and i16 [[PTR]], [[INVERTED_MASK]]
196+
// CHECK-USHORT-NEXT: [[ALIGNED_RESULT:%.*]] = and i16 [[PTR:%.*]], [[INVERTED_MASK]]
209197
// CHECK-USHORT-NEXT: ret i16 [[ALIGNED_RESULT]]
210198
//
211199
TYPE align_down(TYPE ptr, unsigned align) {

0 commit comments

Comments
 (0)