diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index f71d20cf462..e2ebd27b19b 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-73d8e2fecb9e73422464b4cbf71f2b2967c9a75d
+955b8b36f8bbacc59745b44cdf48ef1ddeb01bcd
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
diff --git a/gcc/d/dmd/dinterpret.c b/gcc/d/dmd/dinterpret.c
index 6b4a2b73a7f..ada1d8bc54f 100644
--- a/gcc/d/dmd/dinterpret.c
+++ b/gcc/d/dmd/dinterpret.c
@@ -4465,7 +4465,7 @@ public:
         result = pue->exp();
     }
 
-    void visit(AndAndExp *e)
+    void visit(LogicalExp *e)
     {
         // Check for an insidePointer expression, evaluate it if so
         interpretFourPointerRelation(pue, e);
@@ -4477,9 +4477,10 @@ public:
             return;
 
         int res;
-        if (result->isBool(false))
-            res = 0;
-        else if (isTrueBool(result))
+        const bool andand = e->op == TOKandand;
+        if (andand ? result->isBool(false) : isTrueBool(result))
+            res = !andand;
+        else if (andand ? isTrueBool(result) : result->isBool(false))
         {
             UnionExp ue2;
             result = interpret(&ue2, e->e2, istate);
@@ -4497,64 +4498,14 @@ public:
                 res = 1;
             else
             {
-                result->error("%s does not evaluate to a boolean", result->toChars());
+                result->error("`%s` does not evaluate to a boolean", result->toChars());
                 result = CTFEExp::cantexp;
                 return;
             }
         }
         else
         {
-            result->error("%s cannot be interpreted as a boolean", result->toChars());
-            result = CTFEExp::cantexp;
-            return;
-        }
-        if (goal != ctfeNeedNothing)
-        {
-            new(pue) IntegerExp(e->loc, res, e->type);
-            result = pue->exp();
-        }
-    }
-
-    void visit(OrOrExp *e)
-    {
-        // Check for an insidePointer expression, evaluate it if so
-        interpretFourPointerRelation(pue, e);
-        if (result)
-            return;
-
-        result = interpret(e->e1, istate);
-        if (exceptionOrCant(result))
-            return;
-
-        int res;
-        if (isTrueBool(result))
-            res = 1;
-        else if (result->isBool(false))
-        {
-            UnionExp ue2;
-            result = interpret(&ue2, e->e2, istate);
-            if (exceptionOrCant(result))
-                return;
-            if (result->op == TOKvoidexp)
-            {
-                assert(e->type->ty == Tvoid);
-                result = NULL;
-                return;
-            }
-            if (result->isBool(false))
-                res = 0;
-            else if (isTrueBool(result))
-                res = 1;
-            else
-            {
-                result->error("%s cannot be interpreted as a boolean", result->toChars());
-                result = CTFEExp::cantexp;
-                return;
-            }
-        }
-        else
-        {
-            result->error("%s cannot be interpreted as a boolean", result->toChars());
+            result->error("`%s` cannot be interpreted as a boolean", result->toChars());
             result = CTFEExp::cantexp;
             return;
         }
diff --git a/gcc/d/dmd/expression.c b/gcc/d/dmd/expression.c
index d15081763df..0b21fc949c5 100644
--- a/gcc/d/dmd/expression.c
+++ b/gcc/d/dmd/expression.c
@@ -1895,7 +1895,7 @@ bool functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
                     // edtor => (__gate || edtor)
                     assert(tmp->edtor);
                     Expression *e = tmp->edtor;
-                    e = new OrOrExp(e->loc, new VarExp(e->loc, gate), e);
+                    e = new LogicalExp(e->loc, TOKoror, new VarExp(e->loc, gate), e);
                     tmp->edtor = semantic(e, sc);
                     //printf("edtor: %s\n", tmp->edtor->toChars());
                 }
@@ -6457,28 +6457,12 @@ XorExp::XorExp(Loc loc, Expression *e1, Expression *e2)
 
 /************************************************************/
 
-OrOrExp::OrOrExp(Loc loc, Expression *e1, Expression *e2)
-        : BinExp(loc, TOKoror, sizeof(OrOrExp), e1, e2)
+LogicalExp::LogicalExp(Loc loc, TOK op, Expression *e1, Expression *e2)
+        : BinExp(loc, op, sizeof(LogicalExp), e1, e2)
 {
 }
 
-Expression *OrOrExp::toBoolean(Scope *sc)
-{
-    Expression *ex2 = e2->toBoolean(sc);
-    if (ex2->op == TOKerror)
-        return ex2;
-    e2 = ex2;
-    return this;
-}
-
-/************************************************************/
-
-AndAndExp::AndAndExp(Loc loc, Expression *e1, Expression *e2)
-        : BinExp(loc, TOKandand, sizeof(AndAndExp), e1, e2)
-{
-}
-
-Expression *AndAndExp::toBoolean(Scope *sc)
+Expression *LogicalExp::toBoolean(Scope *sc)
 {
     Expression *ex2 = e2->toBoolean(sc);
     if (ex2->op == TOKerror)
@@ -6591,9 +6575,9 @@ void CondExp::hookDtors(Scope *sc)
                     //printf("\t++v = %s, v->edtor = %s\n", v->toChars(), v->edtor->toChars());
                     Expression *ve = new VarExp(vcond->loc, vcond);
                     if (isThen)
-                        v->edtor = new AndAndExp(v->edtor->loc, ve, v->edtor);
+                        v->edtor = new LogicalExp(v->edtor->loc, TOKandand, ve, v->edtor);
                     else
-                        v->edtor = new OrOrExp(v->edtor->loc, ve, v->edtor);
+                        v->edtor = new LogicalExp(v->edtor->loc, TOKoror, ve, v->edtor);
                     v->edtor = semantic(v->edtor, sc);
                     //printf("\t--v = %s, v->edtor = %s\n", v->toChars(), v->edtor->toChars());
                 }
diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h
index f6ac7c57ee6..e353fdc96a5 100644
--- a/gcc/d/dmd/expression.h
+++ b/gcc/d/dmd/expression.h
@@ -1350,18 +1350,10 @@ public:
     void accept(Visitor *v) { v->visit(this); }
 };
 
-class OrOrExp : public BinExp
+class LogicalExp : public BinExp
 {
 public:
-    OrOrExp(Loc loc, Expression *e1, Expression *e2);
-    Expression *toBoolean(Scope *sc);
-    void accept(Visitor *v) { v->visit(this); }
-};
-
-class AndAndExp : public BinExp
-{
-public:
-    AndAndExp(Loc loc, Expression *e1, Expression *e2);
+    LogicalExp(Loc loc, TOK op, Expression *e1, Expression *e2);
     Expression *toBoolean(Scope *sc);
     void accept(Visitor *v) { v->visit(this); }
 };
diff --git a/gcc/d/dmd/expressionsem.c b/gcc/d/dmd/expressionsem.c
index 412d416715b..e3a5cb36a82 100644
--- a/gcc/d/dmd/expressionsem.c
+++ b/gcc/d/dmd/expressionsem.c
@@ -7445,7 +7445,7 @@ public:
         result = exp;
     }
 
-    void visit(OrOrExp *exp)
+    void visit(LogicalExp *exp)
     {
         if (exp->type)
         {
@@ -7455,7 +7455,6 @@ public:
 
         setNoderefOperands(exp);
 
-        // same as for AndAnd
         Expression *e1x = semantic(exp->e1, sc);
 
         // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
@@ -7471,87 +7470,9 @@ public:
             /* If in static if, don't evaluate e2 if we don't have to.
             */
             e1x = e1x->optimize(WANTvalue);
-            if (e1x->isBool(true))
+            if (e1x->isBool(exp->op == TOKoror))
             {
-                result = new IntegerExp(exp->loc, 1, Type::tbool);
-                return;
-            }
-        }
-
-        Expression *e2x = semantic(exp->e2, sc);
-        sc->mergeCallSuper(exp->loc, cs1);
-
-        // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
-        if (e2x->op == TOKtype)
-            e2x = resolveAliasThis(sc, e2x);
-
-        e2x = resolveProperties(sc, e2x);
-
-        bool f1 = checkNonAssignmentArrayOp(e1x);
-        bool f2 = checkNonAssignmentArrayOp(e2x);
-        if (f1 || f2)
-            return setError();
-
-        // Unless the right operand is 'void', the expression is converted to 'bool'.
-        if (e2x->type->ty != Tvoid)
-            e2x = e2x->toBoolean(sc);
-
-        if (e2x->op == TOKtype || e2x->op == TOKscope)
-        {
-            exp->error("%s is not an expression", exp->e2->toChars());
-            return setError();
-        }
-        if (e1x->op == TOKerror)
-        {
-            result = e1x;
-            return;
-        }
-        if (e2x->op == TOKerror)
-        {
-            result = e2x;
-            return;
-        }
-
-        // The result type is 'bool', unless the right operand has type 'void'.
-        if (e2x->type->ty == Tvoid)
-            exp->type = Type::tvoid;
-        else
-            exp->type = Type::tbool;
-
-        exp->e1 = e1x;
-        exp->e2 = e2x;
-        result = exp;
-    }
-
-    void visit(AndAndExp *exp)
-    {
-        if (exp->type)
-        {
-            result = exp;
-            return;
-        }
-
-        setNoderefOperands(exp);
-
-        // same as for OrOr
-        Expression *e1x = semantic(exp->e1, sc);
-
-        // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
-        if (e1x->op == TOKtype)
-            e1x = resolveAliasThis(sc, e1x);
-
-        e1x = resolveProperties(sc, e1x);
-        e1x = e1x->toBoolean(sc);
-        unsigned cs1 = sc->callSuper;
-
-        if (sc->flags & SCOPEcondition)
-        {
-            /* If in static if, don't evaluate e2 if we don't have to.
-            */
-            e1x = e1x->optimize(WANTvalue);
-            if (e1x->isBool(false))
-            {
-                result = new IntegerExp(exp->loc, 0, Type::tbool);
+                result = new IntegerExp(exp->loc, exp->op == TOKoror, Type::tbool);
                 return;
             }
         }
diff --git a/gcc/d/dmd/opover.c b/gcc/d/dmd/opover.c
index 847cee93d35..66a0d235eee 100644
--- a/gcc/d/dmd/opover.c
+++ b/gcc/d/dmd/opover.c
@@ -1106,9 +1106,9 @@ Expression *op_overload(Expression *e, Scope *sc)
                         if (!result)
                             result = eeq;
                         else if (e->op == TOKequal)
-                            result = new AndAndExp(e->loc, result, eeq);
+                            result = new LogicalExp(e->loc, TOKandand, result, eeq);
                         else
-                            result = new OrOrExp(e->loc, result, eeq);
+                            result = new LogicalExp(e->loc, TOKoror, result, eeq);
                     }
                     assert(result);
                 }
diff --git a/gcc/d/dmd/optimize.c b/gcc/d/dmd/optimize.c
index 82f3aee99fd..e907229be4c 100644
--- a/gcc/d/dmd/optimize.c
+++ b/gcc/d/dmd/optimize.c
@@ -1095,65 +1095,23 @@ Expression *Expression_optimize(Expression *e, int result, bool keepLvalue)
             //printf("-SliceExp::optimize() %s\n", ret->toChars());
         }
 
-        void visit(AndAndExp *e)
+        void visit(LogicalExp *e)
         {
-            //printf("AndAndExp::optimize(%d) %s\n", result, e->toChars());
+            //printf("LogicalExp::optimize(%d) %s\n", result, e->toChars());
             if (expOptimize(e->e1, WANTvalue))
                 return;
-
-            if (e->e1->isBool(false))
-            {
-                // Replace with (e1, false)
-                ret = new IntegerExp(e->loc, 0, Type::tbool);
-                ret = Expression::combine(e->e1, ret);
-                if (e->type->toBasetype()->ty == Tvoid)
-                {
-                    ret = new CastExp(e->loc, ret, Type::tvoid);
-                    ret->type = e->type;
-                }
-                return;
-            }
-
-            if (expOptimize(e->e2, WANTvalue))
-                return;
-
-            if (e->e1->isConst())
-            {
-                if (e->e2->isConst())
-                {
-                    bool n1 = e->e1->isBool(true);
-                    bool n2 = e->e2->isBool(true);
-                    ret = new IntegerExp(e->loc, n1 && n2, e->type);
-                }
-                else if (e->e1->isBool(true))
-                {
-                    if (e->type->toBasetype()->ty == Tvoid)
-                        ret = e->e2;
-                    else
-                    {
-                        ret = new CastExp(e->loc, e->e2, e->type);
-                        ret->type = e->type;
-                    }
-                }
-            }
-        }
-
-        void visit(OrOrExp *e)
-        {
-            //printf("OrOrExp::optimize(%d) %s\n", result, e->toChars());
-            if (expOptimize(e->e1, WANTvalue))
-                return;
-
-            if (e->e1->isBool(true))
+            const bool oror = e->op == TOKoror;
+            if (e->e1->isBool(oror))
             {
-                // Replace with (e1, true)
-                ret = new IntegerExp(e->loc, 1, Type::tbool);
+                // Replace with (e1, oror)
+                ret = new IntegerExp(e->loc, oror, Type::tbool);
                 ret = Expression::combine(e->e1, ret);
                 if (e->type->toBasetype()->ty == Tvoid)
                 {
                     ret = new CastExp(e->loc, ret, Type::tvoid);
                     ret->type = e->type;
                 }
+                ret = ret->optimize(result);
                 return;
             }
 
@@ -1166,9 +1124,9 @@ Expression *Expression_optimize(Expression *e, int result, bool keepLvalue)
                 {
                     bool n1 = e->e1->isBool(true);
                     bool n2 = e->e2->isBool(true);
-                    ret = new IntegerExp(e->loc, n1 || n2, e->type);
+                    ret = new IntegerExp(e->loc, oror ? (n1 || n2) : (n1 && n2), e->type);
                 }
-                else if (e->e1->isBool(false))
+                else if (e->e1->isBool(!oror))
                 {
                     if (e->type->toBasetype()->ty == Tvoid)
                         ret = e->e2;
diff --git a/gcc/d/dmd/parse.c b/gcc/d/dmd/parse.c
index 79acab731a6..4aec7a46e7b 100644
--- a/gcc/d/dmd/parse.c
+++ b/gcc/d/dmd/parse.c
@@ -7773,7 +7773,7 @@ Expression *Parser::parseAndAndExp()
     {
         nextToken();
         e2 = parseOrExp();
-        e = new AndAndExp(loc, e, e2);
+        e = new LogicalExp(loc, TOKandand, e, e2);
     }
     return e;
 }
@@ -7789,7 +7789,7 @@ Expression *Parser::parseOrOrExp()
     {
         nextToken();
         e2 = parseAndAndExp();
-        e = new OrOrExp(loc, e, e2);
+        e = new LogicalExp(loc, TOKoror, e, e2);
     }
     return e;
 }
diff --git a/gcc/d/dmd/sideeffect.c b/gcc/d/dmd/sideeffect.c
index c6448ae19de..efab276d849 100644
--- a/gcc/d/dmd/sideeffect.c
+++ b/gcc/d/dmd/sideeffect.c
@@ -301,15 +301,10 @@ bool discardValue(Expression *e)
             return true;
 
         case TOKandand:
-        {
-            AndAndExp *aae = (AndAndExp *)e;
-            return discardValue(aae->e2);
-        }
-
         case TOKoror:
         {
-            OrOrExp *ooe = (OrOrExp *)e;
-            return discardValue(ooe->e2);
+            LogicalExp *aae = (LogicalExp  *)e;
+            return discardValue(aae->e2);
         }
 
         case TOKquestion:
diff --git a/gcc/d/dmd/staticcond.c b/gcc/d/dmd/staticcond.c
index 72c11a9ec3b..48a60d34fb1 100644
--- a/gcc/d/dmd/staticcond.c
+++ b/gcc/d/dmd/staticcond.c
@@ -28,25 +28,23 @@ Expression *semantic(Expression *e, Scope *sc);
 
 bool evalStaticCondition(Scope *sc, Expression *exp, Expression *e, bool &errors)
 {
-    if (e->op == TOKandand)
+    if (e->op == TOKandand || e->op == TOKoror)
     {
-        AndAndExp *aae = (AndAndExp *)e;
+        LogicalExp *aae = (LogicalExp *)e;
         bool result = evalStaticCondition(sc, exp, aae->e1, errors);
-        if (errors || !result)
-            return false;
-        result = evalStaticCondition(sc, exp, aae->e2, errors);
-        return !errors && result;
-    }
-
-    if (e->op == TOKoror)
-    {
-        OrOrExp *ooe = (OrOrExp *)e;
-        bool result = evalStaticCondition(sc, exp, ooe->e1, errors);
         if (errors)
             return false;
-        if (result)
-            return true;
-        result = evalStaticCondition(sc, exp, ooe->e2, errors);
+        if (e->op == TOKandand)
+        {
+            if (!result)
+                return false;
+        }
+        else
+        {
+            if (result)
+                return true;
+        }
+        result = evalStaticCondition(sc, exp, aae->e2, errors);
         return !errors && result;
     }
 
diff --git a/gcc/d/dmd/visitor.h b/gcc/d/dmd/visitor.h
index dafde3bd87b..8093c94cfee 100644
--- a/gcc/d/dmd/visitor.h
+++ b/gcc/d/dmd/visitor.h
@@ -269,8 +269,7 @@ class UshrExp;
 class AndExp;
 class OrExp;
 class XorExp;
-class OrOrExp;
-class AndAndExp;
+class LogicalExp;
 class CmpExp;
 class InExp;
 class RemoveExp;
@@ -563,8 +562,7 @@ public:
     virtual void visit(AndExp *e) { visit((BinExp *)e); }
     virtual void visit(OrExp *e) { visit((BinExp *)e); }
     virtual void visit(XorExp *e) { visit((BinExp *)e); }
-    virtual void visit(OrOrExp *e) { visit((BinExp *)e); }
-    virtual void visit(AndAndExp *e) { visit((BinExp *)e); }
+    virtual void visit(LogicalExp *e) { visit((BinExp *)e); }
     virtual void visit(CmpExp *e) { visit((BinExp *)e); }
     virtual void visit(InExp *e) { visit((BinExp *)e); }
     virtual void visit(RemoveExp *e) { visit((BinExp *)e); }
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index 562e35a0f7c..41d97964dd3 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -545,11 +545,14 @@ public:
     this->result_ = d_convert (build_ctype (e->type), result);
   }
 
-  /* Build an `and if' expression.  If the right operand expression is void,
-     then the resulting type is void.  Otherwise the result is bool.  */
+  /* Build a logical `and if' or `or if' expression.  If the right operand
+     expression is void, then the resulting type is void.  Otherwise the
+     result is bool.  */
 
-  void visit (AndAndExp *e)
+  void visit (LogicalExp *e)
   {
+    tree_code code = (e->op == TOKandand) ? TRUTH_ANDIF_EXPR : TRUTH_ORIF_EXPR;
+
     if (e->e2->type->toBasetype ()->ty != Tvoid)
       {
 	tree t1 = build_expr (e->e1);
@@ -559,39 +562,19 @@ public:
 	t2 = convert_for_condition (t2, e->e2->type);
 
 	this->result_ = d_convert (build_ctype (e->type),
-				   build_boolop (TRUTH_ANDIF_EXPR, t1, t2));
+				   build_boolop (code, t1, t2));
       }
     else
       {
 	tree t1 = convert_for_condition (build_expr (e->e1), e->e1->type);
 	tree t2 = build_expr_dtor (e->e2);
 
-	this->result_ = build_condition (build_ctype (e->type),
-					 t1, t2, void_node);
-      }
-  }
-
-  /* Build an `or if' expression.  If the right operand expression is void,
-     then the resulting type is void.  Otherwise the result is bool.  */
-
-  void visit (OrOrExp *e)
-  {
-    if (e->e2->type->toBasetype ()->ty != Tvoid)
-      {
-	tree t1 = convert_for_condition (build_expr (e->e1), e->e1->type);
-	tree t2 = convert_for_condition (build_expr (e->e2), e->e2->type);
-
-	this->result_ = d_convert (build_ctype (e->type),
-				   build_boolop (TRUTH_ORIF_EXPR, t1, t2));
-      }
-    else
-      {
-	tree t1 = convert_for_condition (build_expr (e->e1), e->e1->type);
-	tree t2 = build_expr_dtor (e->e2);
-	tree cond = build1 (TRUTH_NOT_EXPR, d_bool_type, t1);
+	/* Invert condition for logical or if expression.  */
+	if (e->op == TOKoror)
+	  t1 = build1 (TRUTH_NOT_EXPR, d_bool_type, t1);
 
 	this->result_ = build_condition (build_ctype (e->type),
-					 cond, t2, void_node);
+					 t1, t2, void_node);
       }
   }
 
