diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java
index ace7e51fb5f2b138103065be13d4b763cc99eaf8..fa35843bb2de35cfebb7f1769f2e83b97353c753 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java
@@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import static com.oracle.truffle.r.runtime.RBuiltinKind.*;
 
 import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.*;
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.utilities.*;
@@ -44,6 +45,7 @@ public abstract class PMinMax extends RBuiltinNode {
     @Child private CastToVectorNode castVector;
     @Child private CastIntegerNode castInteger;
     @Child private CastDoubleNode castDouble;
+    @Child private CastStringNode castString;
     @Child private PrecedenceNode precedenceNode = PrecedenceNodeFactory.create(null, null);
     private final ReduceSemantics semantics;
     private final NACheck na = NACheck.create();
@@ -90,6 +92,14 @@ public abstract class PMinMax extends RBuiltinNode {
         return castDouble;
     }
 
+    private CastNode getStringCastNode() {
+        if (castString == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            castString = insert(CastStringNodeFactory.create(null, true, true, true, false));
+        }
+        return castString;
+    }
+
     private int convertToVectorAndEnableNACheck(VirtualFrame frame, RArgsValuesAndNames args, CastNode castNode) {
         int length = 0;
         Object[] argValues = args.getValues();
@@ -118,7 +128,7 @@ public abstract class PMinMax extends RBuiltinNode {
             boolean warningAdded = false;
             for (int i = 0; i < maxLength; i++) {
                 int result = semantics.getIntStart();
-                for (int j = 0; j < args.length(); j++) {
+                for (int j = 0; j < argValues.length; j++) {
                     RAbstractIntVector vec = (RAbstractIntVector) argValues[j];
                     if (vec.getLength() < maxLength && !warningAdded) {
                         RError.warning(RError.Message.ARG_RECYCYLED);
@@ -158,7 +168,7 @@ public abstract class PMinMax extends RBuiltinNode {
             boolean warningAdded = false;
             for (int i = 0; i < maxLength; i++) {
                 double result = semantics.getDoubleStart();
-                for (int j = 0; j < args.length(); j++) {
+                for (int j = 0; j < argValues.length; j++) {
                     RAbstractDoubleVector vec = (RAbstractDoubleVector) argValues[j];
                     if (vec.getLength() < maxLength && !warningAdded) {
                         RError.warning(RError.Message.ARG_RECYCYLED);
@@ -182,7 +192,75 @@ public abstract class PMinMax extends RBuiltinNode {
         }
     }
 
-    // TODO implement support for strings
+    @SlowPath
+    private boolean doStringVectorMultiElem(Object[] argValues, byte naRm, int offset, int ind, int maxLength, boolean warning, String[] data) {
+        boolean warningAdded = warning;
+        RAbstractStringVector vec = (RAbstractStringVector) argValues[offset];
+        if (vec.getLength() < maxLength && !warningAdded) {
+            RError.warning(RError.Message.ARG_RECYCYLED);
+            warningAdded = true;
+        }
+        String result = vec.getDataAt(ind % vec.getLength());
+        na.enable(result);
+        if (naRm == RRuntime.LOGICAL_TRUE) {
+            if (na.check(result)) {
+                // the following is meant to eliminate leading NA-s
+                if (offset == argValues.length - 1) {
+                    // last element - all other are NAs
+                    data[ind] = semantics.getStringStart();
+                } else {
+                    return doStringVectorMultiElem(argValues, naRm, offset + 1, ind, maxLength, warningAdded, data);
+                }
+                return warningAdded;
+            }
+        } else {
+            if (na.check(result)) {
+                data[ind] = result;
+                return warningAdded;
+            }
+        }
+        // when we reach here, it means that we have already seen one non-NA element
+        assert !RRuntime.isNA(result);
+        for (int i = offset + 1; i < argValues.length; ++i) {
+            vec = (RAbstractStringVector) argValues[i];
+            if (vec.getLength() < maxLength && !warningAdded) {
+                RError.warning(RError.Message.ARG_RECYCYLED);
+                warningAdded = true;
+            }
+
+            String current = vec.getDataAt(ind % vec.getLength());
+            na.enable(current);
+            if (na.check(current)) {
+                if (naRm == RRuntime.LOGICAL_TRUE) {
+                    // skip NA-s
+                    continue;
+                } else {
+                    data[ind] = RRuntime.STRING_NA;
+                    return warningAdded;
+                }
+            } else {
+                result = op.op(result, current);
+            }
+        }
+        data[ind] = result;
+        return warningAdded;
+    }
+
+    @Specialization(guards = "isStringPrecedence")
+    protected RStringVector pMinMaxString(VirtualFrame frame, byte naRm, RArgsValuesAndNames args) {
+        int maxLength = convertToVectorAndEnableNACheck(frame, args, getStringCastNode());
+        if (lengthProfile.profile(maxLength == 0)) {
+            return RDataFactory.createEmptyStringVector();
+        } else {
+            String[] data = new String[maxLength];
+            Object[] argValues = args.getValues();
+            boolean warningAdded = false;
+            for (int i = 0; i < maxLength; i++) {
+                warningAdded = doStringVectorMultiElem(argValues, naRm, 0, i, maxLength, warningAdded, data);
+            }
+            return RDataFactory.createStringVector(data, na.neverSeenNA() || naRm == RRuntime.LOGICAL_TRUE);
+        }
+    }
 
     @SuppressWarnings("unused")
     @Specialization(guards = "isComplexPrecedence")
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java
index ebdfb19762d71002a4aa9aede6419ed713b75532..816f7b1a582cc451b2748b5ab326378d919de53f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java
@@ -343,7 +343,7 @@ public abstract class UnaryArithmeticReduceNode extends UnaryNode {
 
     @SlowPath
     private String doStringVectorMultiElem(RStringVector operand, byte naRm, int offset) {
-        String result = operand.getDataAt(0);
+        String result = operand.getDataAt(offset);
         na.enable(result);
         if (naRm == RRuntime.LOGICAL_TRUE) {
             if (na.check(result)) {
@@ -362,7 +362,7 @@ public abstract class UnaryArithmeticReduceNode extends UnaryNode {
         }
         // when we reach here, it means that we have already seen one non-NA element
         assert !RRuntime.isNA(result);
-        for (int i = 1; i < operand.getLength(); ++i) {
+        for (int i = offset + 1; i < operand.getLength(); ++i) {
             String current = operand.getDataAt(i);
             na.enable(current);
             if (na.check(current)) {
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
index 91d4ff05c9223c12fca304eb14b542a348f964b5..3dcc90774a0b10c9397c695e04c22ee4f8e75e33 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
@@ -9028,6 +9028,14 @@ Error in max(42 + (0+42i), 7 + (0+7i)) :
 Warning message:
 In max(NULL) : no non-missing arguments to max; returning -Inf
 
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testMaximum
+#{ max(as.character(NA), as.character(NA), "42", "7", na.rm=TRUE) }
+[1] "7"
+
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testMaximum
+#{ max(as.character(NA), as.character(NA), "42", na.rm=TRUE) }
+[1] "42"
+
 ##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testMaximum
 #{ max(as.character(NA), as.character(NA), na.rm=FALSE) }
 [1] NA
@@ -9822,6 +9830,37 @@ Error in pmax(7 + (0+42i)) : invalid input type
 #{ pmax(as.raw(42)) }
 Error in pmax(as.raw(42)) : invalid input type
 
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testPMax
+#{ pmax(c("1", "7"), c("42", "1")) }
+[1] "42" "7"
+
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testPMax
+#{ pmax(c("1", "7"), c("42", as.character(NA))) }
+[1] "42" NA
+
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testPMax
+#{ pmax(c("1", "7"), c("42", as.character(NA)), na.rm=TRUE) }
+[1] "42" "7"
+
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testPMax
+#{ pmax(c("1", "7"), character()) }
+character(0)
+
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testPMax
+#{ pmax(c("1", "7", "8"), c("1"), c("42", "1")) }
+[1] "42" "7"  "8"
+Warning message:
+In pmax(c("1", "7", "8"), c("1"), c("42", "1")) :
+  an argument will be fractionally recycled
+
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testPMax
+#{ pmax(c("1", as.character(NA)), c("42", "1"), na.rm=TRUE) }
+[1] "42" "1"
+
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testPMax
+#{ pmax(c("1", as.character(NA)), c(as.character(NA), as.character(NA)), c("42", "1"), na.rm=TRUE) }
+[1] "42" "1"
+
 ##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testPMax
 #{ pmax(c(1, 7), c(42, 1)) }
 [1] 42  7
@@ -9888,6 +9927,37 @@ Error in pmin(7 + (0+42i)) : invalid input type
 #{ pmin(as.raw(42)) }
 Error in pmin(as.raw(42)) : invalid input type
 
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testPMin
+#{ pmin(c("1", "7"), c("42", "1")) }
+[1] "1" "1"
+
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testPMin
+#{ pmin(c("1", "7"), c("42", as.character(NA))) }
+[1] "1" NA
+
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testPMin
+#{ pmin(c("1", "7"), c("42", as.character(NA)), na.rm=TRUE) }
+[1] "1" "7"
+
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testPMin
+#{ pmin(c("1", "7"), character()) }
+character(0)
+
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testPMin
+#{ pmin(c("1", "7", "8"), c("1"), c("42", "1")) }
+[1] "1" "1" "1"
+Warning message:
+In pmin(c("1", "7", "8"), c("1"), c("42", "1")) :
+  an argument will be fractionally recycled
+
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testPMin
+#{ pmin(c("1", as.character(NA)), c("42", "1"), na.rm=TRUE) }
+[1] "1" "1"
+
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testPMin
+#{ pmin(c("1", as.character(NA)), c(as.character(NA), as.character(NA)), c("42", "1"), na.rm=TRUE) }
+[1] "1" "1"
+
 ##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testPMin
 #{ pmin(c(1, 7), c(42, 1)) }
 [1] 1 1
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/all/AllTests.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/all/AllTests.java
index afc37847d9dd9f63951c2bceae372e0dcb4fd685..2c3e6892a33403aff6f367080be47b3b11e913a1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/all/AllTests.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/all/AllTests.java
@@ -10123,6 +10123,16 @@ public class AllTests extends TestBase {
         assertEval("{ max(\"42\", as.character(NA), \"7\", na.rm=FALSE) }");
     }
 
+    @Test
+    public void TestSimpleBuiltins_testMaximum_5e6479a2a6452ee70ccf9c41cef980b1() {
+        assertEval("{ max(as.character(NA), as.character(NA), \"42\", na.rm=TRUE) }");
+    }
+
+    @Test
+    public void TestSimpleBuiltins_testMaximum_ff3b6fdb41d5de0a5783d292d154bd0a() {
+        assertEval("{ max(as.character(NA), as.character(NA), \"42\", \"7\", na.rm=TRUE) }");
+    }
+
     @Test
     public void TestSimpleBuiltins_testMaximum_f5adf3eb65411f16da79fcd519585f41() {
         assertEval("{ max(123, NA, TRUE, 12, FALSE, na.rm=TRUE) }");
@@ -11133,6 +11143,36 @@ public class AllTests extends TestBase {
         assertEval("{ pmax(c(1, 7), c(42, as.double(NA)), na.rm=TRUE) }");
     }
 
+    @Test
+    public void TestSimpleBuiltins_testPMax_0ad681abd0347fc3f329a5de4446750e() {
+        assertEval("{ pmax(c(\"1\", \"7\"), c(\"42\", \"1\")) }");
+    }
+
+    @Test
+    public void TestSimpleBuiltins_testPMax_b03d9fc7b1b74e088e80e50d516b1e27() {
+        assertEval("{ pmax(c(\"1\", \"7\"), character()) }");
+    }
+
+    @Test
+    public void TestSimpleBuiltins_testPMax_280f0aa34b8a627b370c19b2685fcdef() {
+        assertEval("{ pmax(c(\"1\", \"7\"), c(\"42\", as.character(NA))) }");
+    }
+
+    @Test
+    public void TestSimpleBuiltins_testPMax_bad8ae5eb0c03b007b5430b14b0d1c96() {
+        assertEval("{ pmax(c(\"1\", \"7\"), c(\"42\", as.character(NA)), na.rm=TRUE) }");
+    }
+
+    @Test
+    public void TestSimpleBuiltins_testPMax_4a39be88715bd7849ef8a84628a2bfbd() {
+        assertEval("{ pmax(c(\"1\", as.character(NA)), c(\"42\", \"1\"), na.rm=TRUE) }");
+    }
+
+    @Test
+    public void TestSimpleBuiltins_testPMax_ef454dbb5881c936173763ac86ab6816() {
+        assertEval("{ pmax(c(\"1\", as.character(NA)), c(as.character(NA), as.character(NA)), c(\"42\", \"1\"), na.rm=TRUE) }");
+    }
+
     @Test
     public void TestSimpleBuiltins_testPMax_835849fdf0d1b6da7aa2e34dd879e955() {
         assertEval("{ pmax(c(FALSE, TRUE), c(TRUE, FALSE)) }");
@@ -11168,6 +11208,11 @@ public class AllTests extends TestBase {
         assertEvalWarning("{ pmax(c(1, 7, 8), c(1), c(42, 1)) }");
     }
 
+    @Test
+    public void TestSimpleBuiltins_testPMax_7e7482b7816a663ffb8ae05e759fc8c2() {
+        assertEvalWarning("{ pmax(c(\"1\", \"7\", \"8\"), c(\"1\"), c(\"42\", \"1\")) }");
+    }
+
     @Test
     public void TestSimpleBuiltins_testPMin_ed673aa55e7a1c2a8d40c87bcb4e1ada() {
         assertEval("{ pmin(c(1L, 7L), c(42L, 1L)) }");
@@ -11208,6 +11253,36 @@ public class AllTests extends TestBase {
         assertEval("{ pmin(c(1, 7), c(42, as.double(NA)), na.rm=TRUE) }");
     }
 
+    @Test
+    public void TestSimpleBuiltins_testPMin_cba510383b0da53141c20db44e4130cb() {
+        assertEval("{ pmin(c(\"1\", \"7\"), c(\"42\", \"1\")) }");
+    }
+
+    @Test
+    public void TestSimpleBuiltins_testPMin_6c548f27b81ae28280508da7fb1d59d0() {
+        assertEval("{ pmin(c(\"1\", \"7\"), character()) }");
+    }
+
+    @Test
+    public void TestSimpleBuiltins_testPMin_80e247d9adaff94718babba7fd798c59() {
+        assertEval("{ pmin(c(\"1\", \"7\"), c(\"42\", as.character(NA))) }");
+    }
+
+    @Test
+    public void TestSimpleBuiltins_testPMin_9370e766db410333698ba931ad44da9b() {
+        assertEval("{ pmin(c(\"1\", \"7\"), c(\"42\", as.character(NA)), na.rm=TRUE) }");
+    }
+
+    @Test
+    public void TestSimpleBuiltins_testPMin_9f6669bbf3ddb91ddbbb94b07b857347() {
+        assertEval("{ pmin(c(\"1\", as.character(NA)), c(\"42\", \"1\"), na.rm=TRUE) }");
+    }
+
+    @Test
+    public void TestSimpleBuiltins_testPMin_046977a3522a36099d402b3c7dd515cd() {
+        assertEval("{ pmin(c(\"1\", as.character(NA)), c(as.character(NA), as.character(NA)), c(\"42\", \"1\"), na.rm=TRUE) }");
+    }
+
     @Test
     public void TestSimpleBuiltins_testPMin_af8dffea1ee168a9cdae131b7ac14b57() {
         assertEval("{ pmin(c(FALSE, TRUE), c(TRUE, FALSE)) }");
@@ -11243,6 +11318,11 @@ public class AllTests extends TestBase {
         assertEvalWarning("{ pmin(c(1, 7, 8), c(1), c(42, 1)) }");
     }
 
+    @Test
+    public void TestSimpleBuiltins_testPMin_c56e1872347158ba0ec8a2002fec7de9() {
+        assertEvalWarning("{ pmin(c(\"1\", \"7\", \"8\"), c(\"1\"), c(\"42\", \"1\")) }");
+    }
+
     @Test
     public void TestSimpleBuiltins_testParen_499acebd19ac76555ed92ca7ecc3ec53() {
         assertEval("{ a = array(1,c(3,3,3)); (a[1,2,3] = 3) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleBuiltins.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleBuiltins.java
index 4b3895c0806b0ab9b84b6589ef6d4061e2febdb5..33ab8e03d5e629b52e54ee78eb726134666ccf63 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleBuiltins.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleBuiltins.java
@@ -32,6 +32,14 @@ public class TestSimpleBuiltins extends TestBase {
         assertEval("{ pmax(c(1, 7), c(42, as.double(NA))) }");
         assertEval("{ pmax(c(1, 7), c(42, as.double(NA)), na.rm=TRUE) }");
 
+        assertEval("{ pmax(c(\"1\", \"7\"), c(\"42\", \"1\")) }");
+        assertEval("{ pmax(c(\"1\", \"7\"), character()) }");
+        assertEvalWarning("{ pmax(c(\"1\", \"7\", \"8\"), c(\"1\"), c(\"42\", \"1\")) }");
+        assertEval("{ pmax(c(\"1\", \"7\"), c(\"42\", as.character(NA))) }");
+        assertEval("{ pmax(c(\"1\", \"7\"), c(\"42\", as.character(NA)), na.rm=TRUE) }");
+        assertEval("{ pmax(c(\"1\", as.character(NA)), c(\"42\", \"1\"), na.rm=TRUE) }");
+        assertEval("{ pmax(c(\"1\", as.character(NA)), c(as.character(NA), as.character(NA)), c(\"42\", \"1\"), na.rm=TRUE) }");
+
         assertEval("{ pmax(c(FALSE, TRUE), c(TRUE, FALSE)) }");
         assertEval("{ pmax(c(FALSE, TRUE), logical()) }");
         assertEval("{ pmax(c(FALSE, TRUE), c(FALSE, NA)) }");
@@ -54,6 +62,14 @@ public class TestSimpleBuiltins extends TestBase {
         assertEval("{ pmin(c(1, 7), c(42, as.double(NA))) }");
         assertEval("{ pmin(c(1, 7), c(42, as.double(NA)), na.rm=TRUE) }");
 
+        assertEval("{ pmin(c(\"1\", \"7\"), c(\"42\", \"1\")) }");
+        assertEval("{ pmin(c(\"1\", \"7\"), character()) }");
+        assertEvalWarning("{ pmin(c(\"1\", \"7\", \"8\"), c(\"1\"), c(\"42\", \"1\")) }");
+        assertEval("{ pmin(c(\"1\", \"7\"), c(\"42\", as.character(NA))) }");
+        assertEval("{ pmin(c(\"1\", \"7\"), c(\"42\", as.character(NA)), na.rm=TRUE) }");
+        assertEval("{ pmin(c(\"1\", as.character(NA)), c(\"42\", \"1\"), na.rm=TRUE) }");
+        assertEval("{ pmin(c(\"1\", as.character(NA)), c(as.character(NA), as.character(NA)), c(\"42\", \"1\"), na.rm=TRUE) }");
+
         assertEval("{ pmin(c(FALSE, TRUE), c(TRUE, FALSE)) }");
         assertEval("{ pmin(c(FALSE, TRUE), logical()) }");
         assertEval("{ pmin(c(FALSE, TRUE), c(FALSE, NA)) }");
@@ -263,6 +279,9 @@ public class TestSimpleBuiltins extends TestBase {
         assertEval("{ max(\"42\", as.character(NA), \"7\", na.rm=TRUE) }");
         assertEval("{ max(\"42\", as.character(NA), \"7\", na.rm=FALSE) }");
 
+        assertEval("{ max(as.character(NA), as.character(NA), \"42\", na.rm=TRUE) }");
+        assertEval("{ max(as.character(NA), as.character(NA), \"42\", \"7\", na.rm=TRUE) }");
+
         assertEval("{ max(123, NA, TRUE, 12, FALSE, na.rm=TRUE) }");
         assertEval("{ max(123, NA, TRUE, 12, FALSE, na.rm=FALSE) }");
         assertEval("{ max(123, NA, TRUE, 12, FALSE) }");