From 74c273bdb12f19e5ad8c646a6586c17faf3e35dd Mon Sep 17 00:00:00 2001 From: anushkagupta200615-jpg Date: Tue, 16 Jun 2026 01:06:25 +0530 Subject: [PATCH 1/9] Fix #5135: Prevent CondExp from dropping address spaces This fixes an issue in the DCompute backend where ternary condition expressions dropped device address spaces. R-values now use local allocas for the value, and L-values natively preserve pointer types through LLVM PHI nodes. --- gen/toir.cpp | 56 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/gen/toir.cpp b/gen/toir.cpp index 85a0f0d797a..3c1889c9e9e 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -2113,10 +2113,12 @@ class ToElemVisitor : public Visitor { PGO.setCurrentStmt(e); Type *dtype = e->type->toBasetype(); + const bool isLvalue = e->isLvalue(); LLValue *retPtr = nullptr; if (!(dtype->ty == TY::Tvoid || dtype->ty == TY::Tnoreturn)) { - // allocate a temporary for pointer to the final result. - retPtr = DtoAlloca(pointerTo(dtype), "condtmp"); + if (!isLvalue) { + retPtr = DtoAlloca(dtype, "condtmp"); + } } llvm::BasicBlock *condtrue = p->insertBB("condtrue"); @@ -2131,26 +2133,60 @@ class ToElemVisitor : public Visitor { auto branchweights = PGO.createProfileWeights(truecount, falsecount); p->ir->CreateCondBr(cond_val, condtrue, condfalse, branchweights); + LLValue *u_val = nullptr; + llvm::BasicBlock *u_bb = nullptr; p->ir->SetInsertPoint(condtrue); PGO.emitCounterIncrement(e); DValue *u = toElem(e->e1); - if (retPtr && u->type->toBasetype()->ty != TY::Tnoreturn) { - LLValue *lval = makeLValue(e->loc, u); - DtoStore(lval, retPtr); + if (u->type->toBasetype()->ty != TY::Tnoreturn) { + if (isLvalue) { + u_val = makeLValue(e->loc, u); + } else if (retPtr) { + LLValue *rval = DtoRVal(u); + DtoStoreZextI8(rval, retPtr); + } + } + if (!p->scopebb()->getTerminator()) { + u_bb = p->scopebb(); } createBranch(condend, p->scopebb()); + LLValue *v_val = nullptr; + llvm::BasicBlock *v_bb = nullptr; p->ir->SetInsertPoint(condfalse); DValue *v = toElem(e->e2); - if (retPtr && v->type->toBasetype()->ty != TY::Tnoreturn) { - LLValue *lval = makeLValue(e->loc, v); - DtoStore(lval, retPtr); + if (v->type->toBasetype()->ty != TY::Tnoreturn) { + if (isLvalue) { + v_val = makeLValue(e->loc, v); + } else if (retPtr) { + LLValue *rval = DtoRVal(v); + DtoStoreZextI8(rval, retPtr); + } + } + if (!p->scopebb()->getTerminator()) { + v_bb = p->scopebb(); } createBranch(condend, p->scopebb()); p->ir->SetInsertPoint(condend); - if (retPtr) - result = new DSpecialRefValue(e->type, retPtr); + if (isLvalue) { + if (u_bb && v_bb && u_val && v_val) { + llvm::Type *phiType = u_val->getType(); + llvm::PHINode *phi = p->ir->CreatePHI(phiType, 2, "condtmp"); + phi->addIncoming(u_val, u_bb); + if (v_val->getType() != phiType) { + v_val = DtoBitCast(v_val, phiType); + } + phi->addIncoming(v_val, v_bb); + result = new DLValue(e->type, phi); + } else if (u_bb && u_val) { + result = new DLValue(e->type, u_val); + } else if (v_bb && v_val) { + result = new DLValue(e->type, v_val); + } + } else if (retPtr) { + result = new DLValue(e->type, retPtr); + } } ////////////////////////////////////////////////////////////////////////////// From ee37374d8850f119a6882147b49f256afa47dd65 Mon Sep 17 00:00:00 2001 From: anushkagupta200615-jpg Date: Tue, 16 Jun 2026 02:13:47 +0530 Subject: [PATCH 2/9] Fix LLVM IR dominance issue in PHI node generation for CondExp --- gen/toir.cpp | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/gen/toir.cpp b/gen/toir.cpp index 3c1889c9e9e..d168025abc8 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -2170,19 +2170,26 @@ class ToElemVisitor : public Visitor { p->ir->SetInsertPoint(condend); if (isLvalue) { - if (u_bb && v_bb && u_val && v_val) { - llvm::Type *phiType = u_val->getType(); - llvm::PHINode *phi = p->ir->CreatePHI(phiType, 2, "condtmp"); - phi->addIncoming(u_val, u_bb); - if (v_val->getType() != phiType) { - v_val = DtoBitCast(v_val, phiType); + llvm::Type *ptrType = nullptr; + if (u_val) ptrType = u_val->getType(); + else if (v_val) ptrType = v_val->getType(); + else ptrType = DtoPtrToType(dtype); + + if (u_bb && v_bb) { + llvm::PHINode *phi = p->ir->CreatePHI(ptrType, 2, "condtmp"); + phi->addIncoming(u_val ? u_val : llvm::UndefValue::get(ptrType), u_bb); + LLValue *v_inc = v_val ? v_val : llvm::UndefValue::get(ptrType); + if (v_inc->getType() != ptrType) { + v_inc = DtoBitCast(v_inc, ptrType); } - phi->addIncoming(v_val, v_bb); + phi->addIncoming(v_inc, v_bb); result = new DLValue(e->type, phi); - } else if (u_bb && u_val) { - result = new DLValue(e->type, u_val); - } else if (v_bb && v_val) { - result = new DLValue(e->type, v_val); + } else if (u_bb) { + result = new DLValue(e->type, u_val ? u_val : llvm::UndefValue::get(ptrType)); + } else if (v_bb) { + result = new DLValue(e->type, v_val ? v_val : llvm::UndefValue::get(ptrType)); + } else { + result = new DLValue(e->type, llvm::UndefValue::get(ptrType)); } } else if (retPtr) { result = new DLValue(e->type, retPtr); From 28337fea46418c981ac6db5d9c89d92c4c47a77a Mon Sep 17 00:00:00 2001 From: anushkagupta200615-jpg Date: Tue, 16 Jun 2026 02:18:54 +0530 Subject: [PATCH 3/9] Fix compilation error: Use getOpaquePtrType() instead of non-existent DtoPtrToType --- gen/toir.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gen/toir.cpp b/gen/toir.cpp index d168025abc8..5b3ce2e04a7 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -2173,7 +2173,7 @@ class ToElemVisitor : public Visitor { llvm::Type *ptrType = nullptr; if (u_val) ptrType = u_val->getType(); else if (v_val) ptrType = v_val->getType(); - else ptrType = DtoPtrToType(dtype); + else ptrType = getOpaquePtrType(); if (u_bb && v_bb) { llvm::PHINode *phi = p->ir->CreatePHI(ptrType, 2, "condtmp"); From a02705df17bf65e5e1d8661a2581bace4d911712 Mon Sep 17 00:00:00 2001 From: anushkagupta200615-jpg Date: Tue, 16 Jun 2026 03:24:48 +0530 Subject: [PATCH 4/9] Add DCompute codegen test cases for CondExp address spaces (Issue #5135) --- tests/codegen/dcompute_cl_addrspaces.d | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/codegen/dcompute_cl_addrspaces.d b/tests/codegen/dcompute_cl_addrspaces.d index 13c02b16102..015ec5f7975 100644 --- a/tests/codegen/dcompute_cl_addrspaces.d +++ b/tests/codegen/dcompute_cl_addrspaces.d @@ -50,3 +50,21 @@ void foo(GenericPointer!float f) { // LL: load float, ptr addrspace(4) float g = *f; } + +void ternary_rval(GlobalPointer!float f, bool c) { + // LL-LABEL: define{{.*}} @{{.*}}ternary_rval + // LL: load float, ptr addrspace(1) + float g = c ? *f : 0.0f; +} + +void ternary_lval(GlobalPointer!float f, GlobalPointer!float g, bool c) { + // LL-LABEL: define{{.*}} @{{.*}}ternary_lval + // LL: load float, ptr addrspace(1) + float h = c ? *f : *g; +} + +void ternary_lval_assign(GlobalPointer!float f, GlobalPointer!float g, bool c) { + // LL-LABEL: define{{.*}} @{{.*}}ternary_lval_assign + // LL: store float 1.000000e+00, ptr addrspace(1) + (c ? *f : *g) = 1.0f; +} From 31e1544712c8cabcc6ec1ad1cbd4578b9d464df5 Mon Sep 17 00:00:00 2001 From: anushkagupta200615-jpg Date: Wed, 17 Jun 2026 15:34:53 +0530 Subject: [PATCH 5/9] Fix review comments: add null checks and harden PHI path --- gen/toir.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gen/toir.cpp b/gen/toir.cpp index 5b3ce2e04a7..ddea5747438 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -2138,7 +2138,7 @@ class ToElemVisitor : public Visitor { p->ir->SetInsertPoint(condtrue); PGO.emitCounterIncrement(e); DValue *u = toElem(e->e1); - if (u->type->toBasetype()->ty != TY::Tnoreturn) { + if (u && u->type->toBasetype()->ty != TY::Tnoreturn) { if (isLvalue) { u_val = makeLValue(e->loc, u); } else if (retPtr) { @@ -2155,7 +2155,7 @@ class ToElemVisitor : public Visitor { llvm::BasicBlock *v_bb = nullptr; p->ir->SetInsertPoint(condfalse); DValue *v = toElem(e->e2); - if (v->type->toBasetype()->ty != TY::Tnoreturn) { + if (v && v->type->toBasetype()->ty != TY::Tnoreturn) { if (isLvalue) { v_val = makeLValue(e->loc, v); } else if (retPtr) { @@ -2180,7 +2180,7 @@ class ToElemVisitor : public Visitor { phi->addIncoming(u_val ? u_val : llvm::UndefValue::get(ptrType), u_bb); LLValue *v_inc = v_val ? v_val : llvm::UndefValue::get(ptrType); if (v_inc->getType() != ptrType) { - v_inc = DtoBitCast(v_inc, ptrType); + v_inc = p->ir->CreatePointerBitCastOrAddrSpaceCast(v_inc, ptrType); } phi->addIncoming(v_inc, v_bb); result = new DLValue(e->type, phi); From 7461d71d4bd3c51d45e4e2a8c2d26bf63b1634bd Mon Sep 17 00:00:00 2001 From: anushkagupta200615-jpg Date: Wed, 17 Jun 2026 15:44:09 +0530 Subject: [PATCH 6/9] Harden CondExp PHI generation for mismatched address spaces --- gen/toir.cpp | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/gen/toir.cpp b/gen/toir.cpp index ddea5747438..5c31e603380 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -2170,24 +2170,43 @@ class ToElemVisitor : public Visitor { p->ir->SetInsertPoint(condend); if (isLvalue) { - llvm::Type *ptrType = nullptr; - if (u_val) ptrType = u_val->getType(); - else if (v_val) ptrType = v_val->getType(); - else ptrType = getOpaquePtrType(); + llvm::Type *ptrType = getOpaquePtrType(); + if (u_val && v_val && u_val->getType() == v_val->getType()) { + ptrType = u_val->getType(); + } else if (u_val && !v_val) { + ptrType = u_val->getType(); + } else if (v_val && !u_val) { + ptrType = v_val->getType(); + } if (u_bb && v_bb) { llvm::PHINode *phi = p->ir->CreatePHI(ptrType, 2, "condtmp"); - phi->addIncoming(u_val ? u_val : llvm::UndefValue::get(ptrType), u_bb); + + LLValue *u_inc = u_val ? u_val : llvm::UndefValue::get(ptrType); + if (u_inc->getType() != ptrType) { + u_inc = p->ir->CreatePointerBitCastOrAddrSpaceCast(u_inc, ptrType); + } + phi->addIncoming(u_inc, u_bb); + LLValue *v_inc = v_val ? v_val : llvm::UndefValue::get(ptrType); if (v_inc->getType() != ptrType) { v_inc = p->ir->CreatePointerBitCastOrAddrSpaceCast(v_inc, ptrType); } phi->addIncoming(v_inc, v_bb); + result = new DLValue(e->type, phi); } else if (u_bb) { - result = new DLValue(e->type, u_val ? u_val : llvm::UndefValue::get(ptrType)); + LLValue *u_inc = u_val ? u_val : llvm::UndefValue::get(ptrType); + if (u_inc->getType() != ptrType) { + u_inc = p->ir->CreatePointerBitCastOrAddrSpaceCast(u_inc, ptrType); + } + result = new DLValue(e->type, u_inc); } else if (v_bb) { - result = new DLValue(e->type, v_val ? v_val : llvm::UndefValue::get(ptrType)); + LLValue *v_inc = v_val ? v_val : llvm::UndefValue::get(ptrType); + if (v_inc->getType() != ptrType) { + v_inc = p->ir->CreatePointerBitCastOrAddrSpaceCast(v_inc, ptrType); + } + result = new DLValue(e->type, v_inc); } else { result = new DLValue(e->type, llvm::UndefValue::get(ptrType)); } From 6629f125011e3a2c49a8d30d04505b3e771622ea Mon Sep 17 00:00:00 2001 From: gulugulubing <413153391@qq.com> Date: Wed, 17 Jun 2026 07:55:28 -0600 Subject: [PATCH 7/9] Fix crash in CondExp rvalue path for memory-only types Replace DtoRVal + DtoStoreZextI8 with DtoAssign, which correctly handles types that cannot be loaded into a register (e.g. large structs). The previous approach triggered 'getRVal() for memory-only type' assertion in DLValue::getRVal(). --- gen/toir.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gen/toir.cpp b/gen/toir.cpp index 5c31e603380..c1b481dc12f 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -2142,8 +2142,8 @@ class ToElemVisitor : public Visitor { if (isLvalue) { u_val = makeLValue(e->loc, u); } else if (retPtr) { - LLValue *rval = DtoRVal(u); - DtoStoreZextI8(rval, retPtr); + DLValue dst(dtype, retPtr); + DtoAssign(e->loc, &dst, u, EXP::blit); } } if (!p->scopebb()->getTerminator()) { @@ -2159,8 +2159,8 @@ class ToElemVisitor : public Visitor { if (isLvalue) { v_val = makeLValue(e->loc, v); } else if (retPtr) { - LLValue *rval = DtoRVal(v); - DtoStoreZextI8(rval, retPtr); + DLValue dst(dtype, retPtr); + DtoAssign(e->loc, &dst, v, EXP::blit); } } if (!p->scopebb()->getTerminator()) { From 0ad7b7eeddda59d48d9e4b57fd1a5d0bf947761a Mon Sep 17 00:00:00 2001 From: badnikhil Date: Fri, 19 Jun 2026 01:38:12 +0530 Subject: [PATCH 8/9] Fix #5135: Preserve DDcomputeLValue wrapper in CondExp LValue path --- gen/toir.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/gen/toir.cpp b/gen/toir.cpp index c1b481dc12f..71b23a79685 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -2179,6 +2179,8 @@ class ToElemVisitor : public Visitor { ptrType = v_val->getType(); } + LLValue *val = nullptr; + if (u_bb && v_bb) { llvm::PHINode *phi = p->ir->CreatePHI(ptrType, 2, "condtmp"); @@ -2194,21 +2196,29 @@ class ToElemVisitor : public Visitor { } phi->addIncoming(v_inc, v_bb); - result = new DLValue(e->type, phi); + val = phi; } else if (u_bb) { LLValue *u_inc = u_val ? u_val : llvm::UndefValue::get(ptrType); if (u_inc->getType() != ptrType) { u_inc = p->ir->CreatePointerBitCastOrAddrSpaceCast(u_inc, ptrType); } - result = new DLValue(e->type, u_inc); + val = u_inc; } else if (v_bb) { LLValue *v_inc = v_val ? v_val : llvm::UndefValue::get(ptrType); if (v_inc->getType() != ptrType) { v_inc = p->ir->CreatePointerBitCastOrAddrSpaceCast(v_inc, ptrType); } - result = new DLValue(e->type, v_inc); + val = v_inc; + } else { + val = llvm::UndefValue::get(ptrType); + } + + if (auto du = u ? u->isDDcomputeLVal() : nullptr) { + result = new DDcomputeLValue(e->type, du->lltype, val); + } else if (auto dv = v ? v->isDDcomputeLVal() : nullptr) { + result = new DDcomputeLValue(e->type, dv->lltype, val); } else { - result = new DLValue(e->type, llvm::UndefValue::get(ptrType)); + result = new DLValue(e->type, val); } } else if (retPtr) { result = new DLValue(e->type, retPtr); From 27e15b18e7cd953fff1808ecc54049834a4a428b Mon Sep 17 00:00:00 2001 From: badnikhil Date: Fri, 26 Jun 2026 10:56:37 +0530 Subject: [PATCH 9/9] CondExp: factor out the duplicated branch coercion into a lambda the phi/u_bb/v_bb branches all repeated the same undef-or-cast dance; pull it into one incomingFor() helper per review --- gen/toir.cpp | 37 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/gen/toir.cpp b/gen/toir.cpp index 71b23a79685..aa966c549d2 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -2179,36 +2179,27 @@ class ToElemVisitor : public Visitor { ptrType = v_val->getType(); } + // Coerce a branch value to ptrType, substituting undef for a missing + // branch. Bitcast/addrspacecast keeps the address space intact. + auto incomingFor = [&](LLValue *branchVal) { + LLValue *inc = branchVal ? branchVal : llvm::UndefValue::get(ptrType); + if (inc->getType() != ptrType) { + inc = p->ir->CreatePointerBitCastOrAddrSpaceCast(inc, ptrType); + } + return inc; + }; + LLValue *val = nullptr; if (u_bb && v_bb) { llvm::PHINode *phi = p->ir->CreatePHI(ptrType, 2, "condtmp"); - - LLValue *u_inc = u_val ? u_val : llvm::UndefValue::get(ptrType); - if (u_inc->getType() != ptrType) { - u_inc = p->ir->CreatePointerBitCastOrAddrSpaceCast(u_inc, ptrType); - } - phi->addIncoming(u_inc, u_bb); - - LLValue *v_inc = v_val ? v_val : llvm::UndefValue::get(ptrType); - if (v_inc->getType() != ptrType) { - v_inc = p->ir->CreatePointerBitCastOrAddrSpaceCast(v_inc, ptrType); - } - phi->addIncoming(v_inc, v_bb); - + phi->addIncoming(incomingFor(u_val), u_bb); + phi->addIncoming(incomingFor(v_val), v_bb); val = phi; } else if (u_bb) { - LLValue *u_inc = u_val ? u_val : llvm::UndefValue::get(ptrType); - if (u_inc->getType() != ptrType) { - u_inc = p->ir->CreatePointerBitCastOrAddrSpaceCast(u_inc, ptrType); - } - val = u_inc; + val = incomingFor(u_val); } else if (v_bb) { - LLValue *v_inc = v_val ? v_val : llvm::UndefValue::get(ptrType); - if (v_inc->getType() != ptrType) { - v_inc = p->ir->CreatePointerBitCastOrAddrSpaceCast(v_inc, ptrType); - } - val = v_inc; + val = incomingFor(v_val); } else { val = llvm::UndefValue::get(ptrType); }