Skip to content

Commit 92cc923

Browse files
Andrew Savonichevbader
authored andcommitted
[SYCL] Insert addrspacecast for conditional operator
Pointers with the same address space in AST may end up in different address spaces in IR. We cannot CodeGen a conditional operator (ternary 'if') whose operands have different address spaces, so we have to addrspacecast them to generic. Signed-off-by: Andrew Savonichev <andrew.savonichev@intel.com>
1 parent 05442e2 commit 92cc923

File tree

2 files changed

+101
-2
lines changed

2 files changed

+101
-2
lines changed

clang/lib/CodeGen/CGExprScalar.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4160,6 +4160,52 @@ static bool isCheapEnoughToEvaluateUnconditionally(const Expr *E,
41604160
// exist in the source-level program.
41614161
}
41624162

4163+
static Value *insertAddressSpaceCast(Value *V, unsigned NewAS) {
4164+
auto *VTy = cast<llvm::PointerType>(V->getType());
4165+
if (VTy->getAddressSpace() == NewAS)
4166+
return V;
4167+
4168+
llvm::PointerType *VTyNewAS =
4169+
llvm::PointerType::get(VTy->getElementType(), NewAS);
4170+
4171+
if (auto *Constant = dyn_cast<llvm::Constant>(V))
4172+
return llvm::ConstantExpr::getAddrSpaceCast(Constant, VTyNewAS);
4173+
4174+
llvm::Instruction *NewV =
4175+
new llvm::AddrSpaceCastInst(V, VTyNewAS, V->getName() + ".ascast");
4176+
NewV->insertAfter(cast<llvm::Instruction>(V));
4177+
return NewV;
4178+
}
4179+
4180+
static void ensureSameAddrSpace(Value *&RHS, Value *&LHS,
4181+
bool CanInsertAddrspaceCast,
4182+
const LangOptions &Opts,
4183+
const ASTContext &Context) {
4184+
if (RHS->getType() == LHS->getType())
4185+
return;
4186+
4187+
auto *RHSTy = dyn_cast<llvm::PointerType>(RHS->getType());
4188+
auto *LHSTy = dyn_cast<llvm::PointerType>(LHS->getType());
4189+
if (!RHSTy || !LHSTy || RHSTy->getAddressSpace() == LHSTy->getAddressSpace())
4190+
return;
4191+
4192+
if (!CanInsertAddrspaceCast)
4193+
// Pointers have different address spaces and we cannot do anything with
4194+
// this.
4195+
llvm_unreachable("Pointers are expected to have the same address space.");
4196+
4197+
// Language rules define if it is legal to cast from one address space to
4198+
// another, and which address space we should use as a "common
4199+
// denominator". In SYCL, generic address space overlaps with all other
4200+
// address spaces.
4201+
if (Opts.SYCLIsDevice) {
4202+
unsigned GenericAS = Context.getTargetAddressSpace(LangAS::opencl_generic);
4203+
RHS = insertAddressSpaceCast(RHS, GenericAS);
4204+
LHS = insertAddressSpaceCast(LHS, GenericAS);
4205+
} else
4206+
llvm_unreachable("Unable to find a common address space for "
4207+
"two pointers.");
4208+
}
41634209

41644210
Value *ScalarExprEmitter::
41654211
VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
@@ -4256,6 +4302,15 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
42564302
assert(!RHS && "LHS and RHS types must match");
42574303
return nullptr;
42584304
}
4305+
4306+
// Expressions may have the same addrspace in AST, but different address
4307+
// space in LLVM IR, in which case an addrspacecast should be valid.
4308+
bool CanInsertAddrspaceCast = rhsExpr->getType().getAddressSpace() ==
4309+
lhsExpr->getType().getAddressSpace();
4310+
4311+
ensureSameAddrSpace(RHS, LHS, CanInsertAddrspaceCast, CGF.getLangOpts(),
4312+
CGF.getContext());
4313+
42594314
return Builder.CreateSelect(CondV, LHS, RHS, "cond");
42604315
}
42614316

@@ -4290,6 +4345,14 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
42904345
if (!RHS)
42914346
return LHS;
42924347

4348+
// Expressions may have the same addrspace in AST, but different address
4349+
// space in LLVM IR, in which case an addrspacecast should be valid.
4350+
bool CanInsertAddrspaceCast = rhsExpr->getType().getAddressSpace() ==
4351+
lhsExpr->getType().getAddressSpace();
4352+
4353+
ensureSameAddrSpace(RHS, LHS, CanInsertAddrspaceCast, CGF.getLangOpts(),
4354+
CGF.getContext());
4355+
42934356
// Create a PHI node for the real part.
42944357
llvm::PHINode *PN = Builder.CreatePHI(LHS->getType(), 2, "cond");
42954358
PN->addIncoming(LHS, LHSBlock);

clang/test/CodeGenSYCL/address-space-new.cpp

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,46 @@ void test() {
3838
// CHECK-NEW: store i8 addrspace(4)* %[[ARRCAST]], i8 addrspace(4)** %{{.*}}
3939

4040
const char *str = "Hello, world!";
41-
// CHECK-LEGACY: store i8* getelementptr inbounds ([14 x i8], [14 x i8]* @[[STR]], i64 0, i64 0), i8** %{{.*}}, align 8
42-
// CHECK-NEW: store i8 addrspace(4)* addrspacecast (i8* getelementptr inbounds ([14 x i8], [14 x i8]* @[[STR]], i64 0, i64 0) to i8 addrspace(4)*), i8 addrspace(4)** %{{.*}}, align 8
41+
// CHECK-LEGACY: store i8* getelementptr inbounds ([14 x i8], [14 x i8]* @[[STR]], i64 0, i64 0), i8** %[[STRVAL:[a-zA-Z0-9]+]], align 8
42+
// CHECK-NEW: store i8 addrspace(4)* addrspacecast (i8* getelementptr inbounds ([14 x i8], [14 x i8]* @[[STR]], i64 0, i64 0) to i8 addrspace(4)*), i8 addrspace(4)** %[[STRVAL:[a-zA-Z0-9]+]], align 8
4343

4444
i = str[0];
45+
46+
const char *phi_str = i > 2 ? str : "Another hello world!";
47+
(void)phi_str;
48+
// CHECK: %[[COND:[a-zA-Z0-9]+]] = icmp sgt i32 %{{.*}}, 2
49+
// CHECK: br i1 %[[COND]], label %[[CONDTRUE:[.a-zA-Z0-9]+]], label %[[CONDFALSE:[.a-zA-Z0-9]+]]
50+
51+
// CHECK: [[CONDTRUE]]:
52+
// CHECK-LEGACY-NEXT: %[[VALTRUE:[a-zA-Z0-9]+]] = load i8*, i8** %[[STRVAL]]
53+
// CHECK-LEGACY-NEXT: br label %[[CONDEND:[.a-zA-Z0-9]+]]
54+
// CHECK-NEW-NEXT: %[[VALTRUE:[a-zA-Z0-9]+]] = load i8 addrspace(4)*, i8 addrspace(4)** %[[STRVAL]]
55+
// CHECK-NEW-NEXT: br label %[[CONDEND:[.a-zA-Z0-9]+]]
56+
57+
// CHECK: [[CONDFALSE]]:
58+
// CHECK-LEGACY-NEXT: br label %[[CONDEND]]
59+
60+
// CHECK-LEGACY: [[CONDEND]]:
61+
// CHECK-NEW: [[CONDEND]]:
62+
// CHECK-NEW-NEXT: phi i8 addrspace(4)* [ %[[VALTRUE]], %[[CONDTRUE]] ], [ addrspacecast (i8* getelementptr inbounds ([21 x i8], [21 x i8]* @{{.*}}, i64 0, i64 0) to i8 addrspace(4)*), %[[CONDFALSE]] ]
63+
// CHECK-LEGACY-NEXT: phi i8* [ %[[VALTRUE]], %[[CONDTRUE]] ], [ getelementptr inbounds ([21 x i8], [21 x i8]* @{{.*}}, i64 0, i64 0), %[[CONDFALSE]] ]
64+
65+
const char *select_null = i > 2 ? "Yet another Hello world" : nullptr;
66+
(void)select_null;
67+
// CHECK-LEGACY: select i1 %{{.*}}, i8* getelementptr inbounds ([24 x i8], [24 x i8]* @{{.*}}, i64 0, i64 0), i8* null
68+
// CHECK-NEW: select i1 %{{.*}}, i8 addrspace(4)* addrspacecast (i8* getelementptr inbounds ([24 x i8], [24 x i8]* @{{.*}}, i64 0, i64 0) to i8 addrspace(4)*), i8 addrspace(4)* null
69+
70+
const char *select_str_trivial1 = true ? str : "Another hello world!";
71+
(void)select_str_trivial1;
72+
// CHECK-LEGACY: %[[TRIVIALTRUE:[a-zA-Z0-9]+]] = load i8*, i8** %[[STRVAL]]
73+
// CHECK-LEGACY: store i8* %[[TRIVIALTRUE]], i8** %{{.*}}, align 8
74+
// CHECK-NEW: %[[TRIVIALTRUE:[a-zA-Z0-9]+]] = load i8 addrspace(4)*, i8 addrspace(4)** %[[STRVAL]]
75+
// CHECK-NEW: store i8 addrspace(4)* %[[TRIVIALTRUE]], i8 addrspace(4)** %{{.*}}, align 8
76+
77+
const char *select_str_trivial2 = false ? str : "Another hello world!";
78+
(void)select_str_trivial2;
79+
// CHECK-LEGACY: store i8* getelementptr inbounds ([21 x i8], [21 x i8]* @{{.*}}, i64 0, i64 0), i8** %{{.*}}
80+
// CHECK-NEW: store i8 addrspace(4)* addrspacecast (i8* getelementptr inbounds ([21 x i8], [21 x i8]* @{{.*}}, i64 0, i64 0) to i8 addrspace(4)*), i8 addrspace(4)** %{{.*}}
4581
}
4682

4783

0 commit comments

Comments
 (0)