Skip to content

Commit 6554301

Browse files
committed
[SROA] Single-element vectors address space convertion fix
Fixes #139718 When a pointer value is converted into a different address space its original or converted type can be a vector with a single element. In such cases canConvertValue() returns true because of the types equal bitsize, but then a crash in convertValue() is obversed.
1 parent e090900 commit 6554301

File tree

2 files changed

+55
-3
lines changed

2 files changed

+55
-3
lines changed

llvm/lib/Transforms/Scalar/SROA.cpp

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2028,11 +2028,29 @@ static Value *convertValue(const DataLayout &DL, IRBuilderTy &IRB, Value *V,
20282028
// cannot use `bitcast` (which has restrict on the same address space) or
20292029
// `addrspacecast` (which is not always no-op casting). Instead, use a pair
20302030
// of no-op `ptrtoint`/`inttoptr` casts through an integer with the same bit
2031-
// size.
2031+
// size. If the original value is a single-element vector it must be bitcast
2032+
// to a scalar before address space conversion. If the value must be
2033+
// converted to a single-element vector, a bitcast must be added after
2034+
// address space conversion.
20322035
if (OldAS != NewAS) {
20332036
assert(DL.getPointerSize(OldAS) == DL.getPointerSize(NewAS));
2034-
return IRB.CreateIntToPtr(IRB.CreatePtrToInt(V, DL.getIntPtrType(OldTy)),
2035-
NewTy);
2037+
auto ConvertPtrAddrSpace = [&](Value *V, Type *NewTy) {
2038+
return IRB.CreateIntToPtr(
2039+
IRB.CreatePtrToInt(V, DL.getIntPtrType(V->getType())), NewTy);
2040+
};
2041+
if (OldTy->isVectorTy() && !NewTy->isVectorTy()) {
2042+
auto *VecTy = cast<FixedVectorType>(OldTy);
2043+
assert(VecTy->getNumElements() == 1);
2044+
return ConvertPtrAddrSpace(
2045+
IRB.CreateBitCast(V, VecTy->getElementType()), NewTy);
2046+
} else if (!OldTy->isVectorTy() && NewTy->isVectorTy()) {
2047+
auto *VecTy = cast<FixedVectorType>(NewTy);
2048+
assert(VecTy->getNumElements() == 1);
2049+
return IRB.CreateBitCast(
2050+
ConvertPtrAddrSpace(V, VecTy->getElementType()), NewTy);
2051+
} else {
2052+
return ConvertPtrAddrSpace(V, NewTy);
2053+
}
20362054
}
20372055
}
20382056

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
; RUN: opt < %s -passes='sroa<preserve-cfg>' -S | FileCheck %s --check-prefixes=CHECK,CHECK-PRESERVE-CFG
2+
; RUN: opt < %s -passes='sroa<modify-cfg>' -S | FileCheck %s --check-prefixes=CHECK,CHECK-MODIFY-CFG
3+
4+
define ptr addrspace(1) @sev_convert_addrspace_in(<1 x ptr> %arg) {
5+
; CHECK-LABEL: @sev_convert_addrspace_in(
6+
; CHECK-NEXT: entry:
7+
; CHECK-NEXT: [[BITCAST:%.*]] = bitcast <1 x ptr> %arg to ptr
8+
; CHECK-NEXT: [[PTRTOINT:%.*]] = ptrtoint ptr [[BITCAST]] to i64
9+
; CHECK-NEXT: [[INTTOPTR:%.*]] = inttoptr i64 [[PTRTOINT]] to ptr addrspace(1)
10+
; CHECK-NEXT: ret ptr addrspace(1) [[INTTOPTR]]
11+
entry:
12+
%tmp = alloca <1 x ptr>
13+
store <1 x ptr> %arg, ptr %tmp
14+
%res = load ptr addrspace(1), ptr %tmp
15+
ret ptr addrspace(1) %res
16+
}
17+
18+
define <1 x ptr> @sev_convert_addrspace_out(ptr addrspace(1) %arg) {
19+
; CHECK-LABEL: @sev_convert_addrspace_out(
20+
; CHECK-NEXT: entry:
21+
; CHECK-NEXT: [[PTRTOINT:%.*]] = ptrtoint ptr addrspace(1) %arg to i64
22+
; CHECK-NEXT: [[INTTOPTR:%.*]] = inttoptr i64 [[PTRTOINT]] to ptr
23+
; CHECK-NEXT: [[BITCAST:%.*]] = bitcast ptr [[INTTOPTR]] to <1 x ptr>
24+
; CHECK-NEXT: ret <1 x ptr> [[BITCAST]]
25+
entry:
26+
%tmp = alloca ptr addrspace(1)
27+
store ptr addrspace(1) %arg, ptr %tmp
28+
%res = load <1 x ptr>, ptr %tmp
29+
ret <1 x ptr> %res
30+
}
31+
32+
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
33+
; CHECK-MODIFY-CFG: {{.*}}
34+
; CHECK-PRESERVE-CFG: {{.*}}

0 commit comments

Comments
 (0)